This set of docs serves as a reference for the catb project, which is an LLM-based chatbot designed to assist cat owners with theit pets’ health and well-being.
This is the multi-page printable view of this section. Click here to print.
Documentation
- 1: Overview
- 2: CATB MVP Technical Specifications
- 3: CatBot Technical Architecture Specifications
- 4: MVP high level description
- 5: Mu Prompt Management Framework
- 6: Concepts
1 - Overview
Catb is a chatbot helping cat owners understand their cats behaviorial issues so they can take action to solve them.
Catb asks discovery questions about owners’ cats and provides explanations and guidance.
The call to action can range from adapting their interactions or home setting to help with their pets reach optimal mental health all the way to taking their pets to emergency care facilities.
Catb acts as a informed friend that soothes the owners’s anxiety while providing qualified guidance.
Where should I go next?
-
MVP high-level description: A simple overview on the upcoming MVP
-
MVP technical specifications: A more thorough technical description of the upcoming MVP
-
CatBot technical architecture specifications: A broader view on catb’s final version and roadmap
2 - CATB MVP Technical Specifications
CATB MVP Technical Specifications
Table of Contents
- System Overview
- Architecture
- Frontend Architecture
- Backend Architecture
- Database Schema
- Authentication System
- AI Integration
- Infrastructure & Deployment
- Security
- API Reference
- Development & Operations
- Cost Structure
System Overview
Project Description
catb (Cat Health Chatbot) is a production-ready full-stack application providing empathetic cat health guidance through an AI-powered chat interface. The system uses Anthropic’s Claude Sonnet 4 with a custom “Mu” system prompt to deliver personalized, context-aware responses using a progressive discovery approach.
Brand Name: Ask Mü Production URL: https://askmu.live Status: ✅ Fully Operational Deployment Date: September 2025 Last Major Update: October 2025 (Session-email association fix, ProfileService integration)
Current Production Status
- Frontend: React SPA deployed in Docker container (port 3001)
- Backend: Express 5.1.0 API deployed in Docker container (port 3000)
- Database: Supabase PostgreSQL (connected and operational)
- AI: Claude Sonnet 4 with Mu system prompt v3
- Infrastructure: Hostinger VPS at 89.116.170.226
- Domain: askmu.live with SSL (Let’s Encrypt)
- Authentication: Magic link email system with 24-hour sessions
Technology Stack Summary
| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Frontend | React | 18+ | UI framework |
| Tailwind CSS | 3+ | Styling | |
| Radix UI | Latest | Accessible components | |
| Framer Motion | Latest | Animations | |
| Vite | Latest | Build tool | |
| Backend | Node.js | 20 LTS | Runtime |
| Express | 5.1.0 | Web framework | |
| @anthropic-ai/sdk | 0.17.1 | Claude API client | |
| @langchain/anthropic | 0.3.28 | LangChain integration | |
| @supabase/supabase-js | 2.39.0 | Database client | |
| Resend | 2.1.0 | Email service | |
| Database | PostgreSQL | 15 | Supabase managed |
| Infrastructure | Ubuntu | 24.04 LTS | VPS OS |
| Nginx | Latest | Reverse proxy | |
| Docker | Latest | Containerization | |
| Let’s Encrypt | - | SSL certificates |
Access Points
- Production Frontend: https://askmu.live/
- Production API: https://askmu.live/api/
- Health Check: https://askmu.live/api/health
- VPS: 89.116.170.226 (SSH access)
- Email: mu@transactional.askmu.live
Architecture
High-Level System Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Internet │
│ (HTTPS - Port 443) │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Hostinger VPS │
│ (89.116.170.226) │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Nginx Reverse Proxy (Ports 80/443) │ │
│ │ • SSL Termination (Let's Encrypt) │ │
│ │ • Request Routing │ │
│ │ • Security Headers │ │
│ └──────┬────────────────────────────────┬──────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Frontend │ │ Backend API │ │
│ │ Docker Container │ │ Docker Container │ │
│ │ Port 3001 │ │ Port 3000 │ │
│ │ (React SPA) │◄──────────►│ (Express 5.1.0) │ │
│ └──────────────────┘ └────────┬─────────┘ │
│ │ │
└────────────────────────────────────────────┼─────────────────────┘
│
┌────────────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌──────────────┐
│ Supabase │ │ Anthropic │ │ Resend │
│ PostgreSQL │ │ Claude API │ │ Email API │
│ (Database) │ │ (AI Service) │ │ (Magic Links)│
└────────────────┘ └────────────────┘ └──────────────┘
Component Relationships
Frontend (React)
│
├──> State Management (React Hooks + localStorage)
├──> UI Components (Radix UI + Tailwind)
├──> API Client (fetch)
│
└──> Backend API (Express)
│
├──> Authentication Layer
│ ├──> Magic Link System (Resend)
│ ├──> Session Management (Supabase)
│ └──> Token Validation
│
├──> Chat Endpoint
│ ├──> Mu Prompt System
│ │ ├──> Context Analyzer
│ │ ├──> Memory System
│ │ └──> LangChain User Profiler
│ │
│ ├──> Claude AI Integration
│ ├──> ProfileService
│ └──> Conversation History
│
├──> Database Layer (db.js)
│ ├──> User Management
│ ├──> Session Management
│ ├──> Message Storage
│ └──> Context Tracking
│
└──> Enhanced Systems
├──> Pattern Detection Engine
├──> Feedback System
└──> Smart Deployment System
Data Flow
User → Frontend → Nginx → Backend API → Claude AI
↓
Supabase DB
↓
Backend API → Frontend → User
Detailed Flow:
- User sends message from React interface
- Frontend sends authenticated request to backend
- Nginx routes
/api/*requests to backend (port 3000) - Backend validates session token via Supabase
- Backend retrieves conversation history
- Mu Prompt System generates dynamic prompt
- LangChain profiler analyzes user communication style
- Backend sends context + message to Claude API
- Claude generates empathetic response
- Backend saves message pair to database
- Backend returns response to frontend
- Frontend displays reply with animations
Frontend Architecture
Technology Stack
- Framework: React 18+
- Styling: Tailwind CSS 3+
- UI Components: Radix UI (accessible primitives)
- Animations: Framer Motion
- Build Tool: Vite
- Deployment: Docker container (Nginx serving static files)
Application Structure
catb-frontend/
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── ChatBubble.jsx
│ │ ├── ChatInput.jsx
│ │ ├── LoadingIndicator.jsx
│ │ └── EmergencyAlert.jsx
│ │
│ ├── pages/ # Application pages
│ │ ├── Home.jsx
│ │ ├── Chat.jsx
│ │ └── Auth.jsx
│ │
│ ├── lib/ # Utilities and helpers
│ │ ├── api.js # API client
│ │ └── auth.js # Auth helpers
│ │
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.js
│ │ └── useChat.js
│ │
│ ├── styles/ # Global styles
│ │ └── globals.css
│ │
│ ├── App.jsx # Main app component
│ └── main.jsx # Entry point
│
├── public/ # Static assets
│ ├── favicon.svg
│ ├── mascot.png
│ └── doctor.gif
│
├── Dockerfile # Frontend Docker config
├── nginx.conf # Nginx configuration
├── tailwind.config.js # Tailwind configuration
├── vite.config.js # Vite configuration
└── package.json
Key Features
Mobile-First Responsive Design
- Optimized for mobile devices (primary use case: worried pet owners)
- Touch-friendly UI elements
- Responsive breakpoints for tablet and desktop
State Management
- React hooks for local state
- localStorage for session persistence
- No external state management library (keeping it simple)
API Integration
// API client pattern
const apiClient = {
baseURL: 'https://askmu.live/api',
async chat(message, sessionToken) {
const response = await fetch(`${this.baseURL}/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, sessionToken })
});
return response.json();
}
};
Docker Containerization
Dockerfile (Multi-stage build):
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Deployment:
- Container name:
catb-frontend - Internal port: 80
- External port: 3001
- Served by Nginx within container
- Static assets included in image
Backend Architecture
Express 5.1.0 Application Structure
catb-backend/
├── server.js # Main Express application
├── db.js # Database abstraction layer
├── auth-routes.js # Authentication endpoints
├── auth-utils.js # Auth utilities
├── email-service.js # Magic link email service
├── profile-service.js # User/cat profile management
│
├── lib/ # Core libraries
│ ├── mu-prompt-system.js # Main prompt orchestrator
│ ├── conversation-context-analyzer.js
│ ├── conversation-memory-system.js
│ ├── simple-template-engine.js
│ ├── enhanced-feedback-system.js
│ ├── pattern-detection-engine.js
│ ├── smart-deployment-system.js
│ └── langchain/
│ └── langchain-user-profiler.js
│
├── prompts/ # PromptL templates
│ ├── base-prompt.promptl
│ └── [additional templates]
│
├── migrations/ # Database migrations
│ └── 000-complete-fresh-schema.sql
│
├── scripts/ # Utility scripts
│ ├── deploy-to-vps.sh
│ ├── db-connection-helper.js
│ ├── execute-sql.js
│ └── run-daily-workflow.js
│
├── test/ # Test files
│ ├── test-session-email-fix.js
│ └── comprehensive-auth-test.js
│
├── Dockerfile
├── docker-compose.yml
├── package.json
└── .env
Core Dependencies
{
"dependencies": {
"express": "^5.1.0",
"@anthropic-ai/sdk": "^0.17.1",
"@langchain/anthropic": "^0.3.28",
"@langchain/core": "^0.3.77",
"@langchain/langgraph": "^0.4.9",
"@supabase/supabase-js": "^2.39.0",
"cors": "^2.8.5",
"helmet": "^7.1.0",
"express-rate-limit": "^7.1.5",
"resend": "^2.1.0",
"redis": "^5.8.2",
"pg": "^8.16.3",
"validator": "^13.15.15",
"zod": "^3.25.76"
}
}
API Endpoints
Public Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /health |
System health check | No |
| POST | /session/create |
Create authenticated session | No |
| POST | /auth/request-invite |
Request magic link | No |
| GET | /auth/verify |
Verify magic link token | No |
Protected Endpoints (Require sessionToken)
| Method | Endpoint | Description | Rate Limit |
|---|---|---|---|
| POST | /chat or /api/chat |
Main chat endpoint | 10 req/min |
| POST | /api/feedback/submit |
Submit user feedback | 10 req/min |
| GET | /api/dashboard/metrics |
System metrics | 10 req/min |
| GET | /api/patterns/recent |
Recent patterns | 10 req/min |
Middleware Stack
// server.js middleware chain
app.use(helmet()); // Security headers
app.use(cors(corsOptions)); // CORS policy
app.use(express.json()); // JSON body parser
app.use(rateLimiter); // Rate limiting (Redis + memory fallback)
app.use(inputValidator); // Input sanitization
Session Management
Modern Authentication Flow (October 2025 Update):
- ✅ Uses
user_sessionstable with proper foreign keys - ✅ All sessions linked to email addresses
- ❌ Legacy
sessionstable fallback removed - Session validation:
db.validateUserSession(sessionToken)
// Session validation (server.js)
const userSession = await db.validateUserSession(sessionToken);
if (!userSession.valid) {
return res.status(401).json({
error: 'Invalid or expired session'
});
}
sessionId = userSession.sessionId;
userId = userSession.userId; // Always available!
Claude AI Integration
Configuration:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 300,
messages: conversationHistory
});
Cost Control:
- Max tokens per response: 300
- Input tokens: $3 per 1M tokens
- Output tokens: $15 per 1M tokens
- Average cost per interaction: $0.001-0.005
ProfileService Integration
Features:
- User profile management (name, email, preferences)
- Cat profile management (name, age, breed, gender, medical history)
- Profile restoration across sessions
- Validation with Zod schemas
- LangChain integration for behavioral profiling
// ProfileService usage
const profiles = await profileService.restoreProfileForSession(userId);
// Returns: { userProfile, catProfile }
Security Features
- Input Validation: All inputs sanitized with
validatorlibrary - Rate Limiting: Redis-backed with in-memory fallback (10 req/min)
- CORS: Strict origin policy (
https://askmu.live) - Helmet: Security headers (CSP, HSTS, X-Frame-Options)
- Container Security: Non-root user, read-only filesystem
- Port Binding: Backend only accessible via nginx (127.0.0.1:3000)
Database Schema
Supabase PostgreSQL Configuration
Connection:
- URL:
https://PROJECT_REF.supabase.co - Client: @supabase/supabase-js (JavaScript CRUD)
- Direct: PostgreSQL client (DDL operations)
- Authentication: Service role key
Core Tables
users
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP WITH TIME ZONE,
is_active BOOLEAN DEFAULT true,
invitation_sent_at TIMESTAMP WITH TIME ZONE,
first_login_at TIMESTAMP WITH TIME ZONE,
CONSTRAINT email_format CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
);
CREATE INDEX idx_users_email ON users(email);
magic_links
CREATE TABLE magic_links (
link_id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
token TEXT UNIQUE NOT NULL,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
used_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ip_address INET,
user_agent TEXT,
CONSTRAINT token_length CHECK (length(token) >= 32)
);
user_sessions
CREATE TABLE user_sessions (
session_id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
session_token TEXT UNIQUE NOT NULL,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
last_activity TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ip_address INET,
user_agent TEXT,
CONSTRAINT session_token_length CHECK (length(session_token) >= 32)
);
CREATE INDEX idx_user_sessions_token ON user_sessions(session_token);
CREATE INDEX idx_user_sessions_user ON user_sessions(user_id, is_active);
CREATE INDEX idx_user_sessions_active ON user_sessions(is_active, expires_at);
messages
CREATE TABLE messages (
message_id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES user_sessions(session_id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(user_id) ON DELETE CASCADE,
sender VARCHAR(20) NOT NULL CHECK (sender IN ('user', 'assistant')),
message_text TEXT NOT NULL,
token_count INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
message_metadata JSONB DEFAULT '{}'::jsonb
);
CREATE INDEX idx_messages_user ON messages(user_id, created_at DESC);
CREATE INDEX idx_messages_session ON messages(session_id, created_at DESC);
conversation_context
CREATE TABLE conversation_context (
context_id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES user_sessions(session_id) ON DELETE CASCADE,
message_id INTEGER,
context_type VARCHAR(50) NOT NULL DEFAULT 'general',
context_data JSONB NOT NULL DEFAULT '{}',
user_id INTEGER REFERENCES users(user_id),
cat_name VARCHAR(100),
cat_age INTEGER,
cat_breed VARCHAR(100),
cat_gender VARCHAR(20),
current_symptoms TEXT[],
anxiety_level VARCHAR(20),
experience_level VARCHAR(20),
communication_style VARCHAR(20),
emotional_state VARCHAR(30),
conversation_phase VARCHAR(30),
question_count INTEGER DEFAULT 0,
topics_discussed TEXT[],
urgency_indicators TEXT[],
information_completeness JSONB DEFAULT '{}',
confidence_score DECIMAL(3,2),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT conversation_context_session_message_type_key
UNIQUE(session_id, message_id, context_type)
);
CREATE INDEX idx_conversation_context_session ON conversation_context(session_id);
CREATE INDEX idx_conversation_context_user ON conversation_context(user_id);
Profile Tables
user_profiles
CREATE TABLE user_profiles (
profile_id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
full_name VARCHAR(255),
timezone VARCHAR(50),
notification_preferences JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_user_profile UNIQUE(user_id)
);
cat_profiles
CREATE TABLE cat_profiles (
cat_id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
cat_name VARCHAR(100) NOT NULL,
cat_age INTEGER,
cat_breed VARCHAR(100),
cat_gender VARCHAR(20),
medical_history JSONB DEFAULT '[]',
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
Enhanced Tables
feedback_submissions
CREATE TABLE feedback_submissions (
feedback_id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES user_sessions(session_id),
user_id INTEGER REFERENCES users(user_id),
feedback_type VARCHAR(50) NOT NULL,
feedback_data JSONB NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
detected_patterns
CREATE TABLE detected_patterns (
pattern_id SERIAL PRIMARY KEY,
pattern_type VARCHAR(100) NOT NULL,
pattern_data JSONB NOT NULL,
confidence_score DECIMAL(5,4),
detected_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
Cleanup Functions
-- Cleanup expired sessions
CREATE OR REPLACE FUNCTION cleanup_expired_user_sessions()
RETURNS void AS $$
BEGIN
UPDATE user_sessions
SET is_active = false
WHERE expires_at < CURRENT_TIMESTAMP AND is_active = true;
END;
$$ LANGUAGE plpgsql;
-- Cleanup expired magic links
CREATE OR REPLACE FUNCTION cleanup_expired_magic_links()
RETURNS void AS $$
BEGIN
DELETE FROM magic_links
WHERE expires_at < CURRENT_TIMESTAMP;
END;
$$ LANGUAGE plpgsql;
Authentication System
Magic Link Authentication Flow
┌─────────┐ ┌──────────┐
│ User │ │ Backend │
└────┬────┘ └────┬─────┘
│ │
│ 1. Request Access (email) │
├─────────────────────────────────────────────────────────────►
│ │
│ 2. Create user
│ 3. Generate token
│ 4. Save magic_link
│ │
│ 5. Email with magic link ◄───────────────────────────────────┤
├──────────────────────────┐ │
│ │ 6. Click link │
│◄─────────────────────────┘ │
│ │
│ 7. Verify token │
├─────────────────────────────────────────────────────────────►
│ │
│ 8. Validate token
│ 9. Create session
│ 10. Generate sessionToken
│ │
│ 11. Redirect with sessionToken ◄─────────────────────────────┤
│ │
│ 12. Store in localStorage │
├──────────────────────────┐ │
│◄─────────────────────────┘ │
│ │
│ 13. Chat with sessionToken │
├─────────────────────────────────────────────────────────────►
Endpoints
1. Request Magic Link
POST /auth/request-invite
// Request
{
"email": "user@example.com"
}
// Response
{
"success": true,
"message": "Check your email for the invitation link"
}
2. Verify Magic Link
GET /auth/verify?token=MAGIC_LINK_TOKEN
- Validates token from database
- Checks expiration (1 hour)
- Creates user session (24 hours)
- Redirects to frontend with sessionToken
3. Create Session (Direct API)
POST /session/create
// Request
{
"email": "user@example.com"
}
// Response
{
"sessionToken": "64-character-hex-string",
"expiresAt": "2025-10-02T18:30:00.000Z",
"sessionId": 171,
"userId": 425,
"isNewUser": false,
"profiles": {
"userProfile": { ... },
"catProfile": { ... }
}
}
Session Management
Session Lifecycle:
- Creation: Generated when user verifies magic link or via
/session/create - Duration: 24 hours from creation
- Storage:
user_sessionstable in database - Client Storage: localStorage in browser
- Validation: Every API request validates via
db.validateUserSession() - Expiration: Automatic after 24 hours
- Cleanup: Background job marks expired sessions inactive
Token Format:
- Length: 64 characters
- Type: Hexadecimal string
- Generation:
crypto.randomBytes(32).toString('hex') - Uniqueness: Database constraint ensures uniqueness
Session Validation (server.js):
// Modern session validation (October 2025)
const userSession = await db.validateUserSession(sessionToken);
if (!userSession.valid) {
return res.status(401).json({
error: 'Invalid or expired session',
message: 'Please request a new invitation to access Ask Mü'
});
}
// userSession contains:
// - valid: true/false
// - sessionId: integer
// - userId: integer (always present!)
// - email: string (linked via users table)
Email Service (Resend)
Configuration:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'mu@transactional.askmu.live',
to: userEmail,
subject: 'Your invitation to Ask Mü',
html: magicLinkEmailTemplate
});
DNS Records (configured at Namecheap):
- SPF:
v=spf1 include:_spf.resend.com ~all - DKIM: Resend-provided keys
- DMARC:
v=DMARC1; p=none
AI Integration
Anthropic Claude API
Model: claude-sonnet-4-20250514
API Version: @anthropic-ai/sdk 0.17.1
Max Tokens: 300 per response
Temperature: 0.7 (balanced creativity)
API Call Pattern:
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 300,
messages: conversationHistory, // Array of {role, content}
system: generatedPrompt // Dynamic Mu prompt
});
Mu Prompt System
Architecture:
MuPromptSystem (Orchestrator)
│
├──> ConversationContextAnalyzer
│ ├── Analyzes user messages
│ ├── Extracts cat profile info
│ ├── Detects urgency signals
│ └── Identifies communication style
│
├──> ConversationMemorySystem
│ ├── Retrieves conversation history
│ ├── Updates context in database
│ └── Manages conversation phases
│
├──> LangChainUserProfiler
│ ├── Behavioral profiling (2+ messages)
│ ├── Communication style detection
│ ├── Anxiety level assessment
│ └── Experience level classification
│
└──> SimpleTemplateEngine
├── Loads PromptL templates
├── Interpolates context data
└── Generates final prompt
Progressive Discovery Protocol:
- Max 2 Questions Per Response: Core constraint to avoid overwhelming users
- Context-Aware: Analyzes existing information before asking
- Urgency-Sensitive: Prioritizes emergency symptoms
- Adaptive Tone: Adjusts based on user’s communication style
Example Prompt Structure:
You are Mu, an empathetic cat health assistant.
CURRENT CONTEXT:
- Cat: Luna, 3 years old, female
- Symptoms: vomiting, lethargy
- Anxiety Level: high
- Communication Style: emotional support seeker
CONVERSATION PHASE: symptom_gathering
QUESTIONS ASKED: 1/2
INSTRUCTIONS:
- Ask maximum 2 questions
- Prioritize emergency symptoms
- Use warm, empathetic tone
- Provide actionable guidance
LangChain Integration
User Profiling (lib/langchain/langchain-user-profiler.js):
// Triggered after 2+ user messages
const profile = await langchainProfiler.analyzeUserProfile(
conversationHistory,
currentMessage
);
// Returns:
{
profile: {
communicationStyle: 'emotional' | 'factual' | 'low-literacy',
anxietyLevel: 'low' | 'moderate' | 'high' | 'panic',
experienceLevel: 'first-time' | 'beginner' | 'experienced',
preferredResponseStyle: 'concise' | 'detailed',
confidenceLevel: 'low' | 'moderate' | 'high',
learningPreference: 'step-by-step' | 'overview'
},
confidence: {
overall: 0.85,
factorScores: { ... }
},
personalityProfile: {
name: 'Anxious First-Timer',
traits: [...],
responseGuidance: '...'
},
adaptationTriggers: [...]
}
Early Profiling (October 2025):
- Enabled by default
- Activates at 2nd user message (previously 3rd)
- Provides faster personalization
- Fallback to basic analysis if LangChain fails
Conversation Context
Tracked Data:
- Cat Profile: name, age, breed, gender
- Symptoms: current and historical
- Urgency Signals: emergency, urgent, routine indicators
- User Traits: anxiety level, experience level, communication style
- Conversation State: phase, question count, topics discussed
- Information Completeness: gaps in critical information
Context Updates:
await memorySystem.updateConversationContext(sessionId, {
catProfile: { name: 'Luna', age: 3 },
symptoms: ['vomiting', 'lethargy'],
anxietyLevel: 'high',
conversationPhase: 'symptom_gathering',
questionCount: 1
});
Infrastructure & Deployment
VPS Configuration
Provider: Hostinger IP Address: 89.116.170.226 Operating System: Ubuntu 24.04 LTS Resources: Shared VPS plan (~$20-50/month)
Installed Software:
- Docker & Docker Compose
- Nginx
- Certbot (Let’s Encrypt)
- UFW (Uncomplicated Firewall)
- fail2ban (brute force protection)
Port Configuration
| Port | Service | Binding | Purpose |
|---|---|---|---|
| 22 | SSH | 0.0.0.0 | Server access |
| 80 | Nginx | 0.0.0.0 | HTTP → HTTPS redirect |
| 443 | Nginx | 0.0.0.0 | HTTPS termination |
| 3000 | Backend | 127.0.0.1 | Internal only (via nginx) |
| 3001 | Frontend | 127.0.0.1 | Internal only (via nginx) |
Nginx Configuration
File: /etc/nginx/sites-enabled/askmu-live
Routing Rules:
# API endpoints → Backend (port 3000)
location ~ ^/api/(.*)$ {
proxy_pass http://127.0.0.1:3000/$1; # Rewrite /api/* → /*
}
location /auth/ {
proxy_pass http://127.0.0.1:3000;
}
location /session/ {
proxy_pass http://127.0.0.1:3000;
}
location /chat {
proxy_pass http://127.0.0.1:3000;
}
location /health {
proxy_pass http://127.0.0.1:3000;
}
# Frontend → React SPA (port 3001)
location / {
proxy_pass http://127.0.0.1:3001;
try_files $uri $uri/ /index.html; # SPA routing
}
# Static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://127.0.0.1:3001;
expires 1y;
add_header Cache-Control "public, immutable";
}
Docker Configuration
Backend (docker-compose.yml)
version: '3.8'
services:
app:
build: .
container_name: catb-api
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000" # Bind to localhost only
environment:
- NODE_ENV=production
- PORT=3000
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_SERVICE_KEY=${SUPABASE_SERVICE_KEY}
- RESEND_API_KEY=${RESEND_API_KEY}
- FRONTEND_URL=https://askmu.live
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://localhost:3000/health')"]
interval: 30s
timeout: 10s
retries: 3
Frontend (Dockerfile)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Deployment Commands:
# Backend
cd /root/catb/
docker-compose down
docker-compose build --no-cache
docker-compose up -d
# Frontend
cd /root/catb-frontend/
docker stop catb-frontend
docker rm catb-frontend
docker build -t catb-frontend . --no-cache
docker run -d --name catb-frontend --restart unless-stopped -p 127.0.0.1:3001:80 catb-frontend
SSL/TLS Configuration
Provider: Let’s Encrypt
Auto-Renewal: Certbot cron job
Certificate Path: /etc/letsencrypt/live/askmu.live/
Initial Setup:
certbot --nginx -d askmu.live -d www.askmu.live
Renewal:
certbot renew # Auto-scheduled via cron
Deployment Script
File: scripts/deploy-to-vps.sh
#!/bin/bash
# Deployment script for catb backend
VPS="root@89.116.170.226"
APP_DIR="/root/catb"
# Sync files
rsync -av --exclude 'node_modules' --exclude '.git' \
./ ${VPS}:${APP_DIR}/
# Deploy on VPS
ssh ${VPS} << 'EOF'
cd /root/catb
docker-compose down
docker-compose build --no-cache
docker-compose up -d
docker ps | grep catb
EOF
echo "✅ Deployment complete"
Directory Structure (VPS)
/root/
├── catb/ # Backend directory
│ ├── server.js
│ ├── db.js
│ ├── lib/
│ ├── prompts/
│ ├── migrations/
│ ├── scripts/
│ ├── docker-compose.yml
│ ├── Dockerfile
│ ├── .env
│ └── package.json
│
├── catb-frontend/ # Frontend directory
│ ├── src/
│ ├── public/
│ ├── Dockerfile
│ ├── nginx.conf
│ └── package.json
│
└── scripts/ # System scripts
├── setup-ssl.sh
└── setup-domain.sh
Security
Authentication Security
-
Magic Link Tokens:
- 64-character cryptographically secure random strings
- 1-hour expiration
- Single-use only (marked as
used_atafter verification) - Stored with user_agent and IP for audit trail
-
Session Tokens:
- 64-character cryptographically secure random strings
- 24-hour expiration
- Validated on every request
- Linked to user_id (email association enforced)
-
Password-less Authentication:
- No passwords to leak or crack
- Email-based access control
- Reduces attack surface
Input Validation
Library: validator v13.15.15
import validator from 'validator';
// Email validation
const isValidEmail = validator.isEmail(email);
// Message sanitization
const sanitizedMessage = validator.escape(message);
validator.isLength(message, { max: 2000 });
// Token validation
const isValidToken = /^[a-f0-9]{64}$/.test(token);
Rate Limiting
Strategy: Redis-backed with in-memory fallback
import rateLimit from 'express-rate-limit';
import RedisStore from 'rate-limit-redis';
const chatLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10, // 10 requests per minute
store: new RedisStore({
client: redisClient,
prefix: 'rl:chat:'
}),
// Fallback to memory if Redis unavailable
skipFailedRequests: false,
standardHeaders: true,
legacyHeaders: false
});
app.post('/chat', chatLimiter, chatHandler);
Current Status:
- Redis not deployed (falls back to in-memory)
- Sufficient for single-instance VPS deployment
- Consider Redis when scaling horizontally
CORS Configuration
import cors from 'cors';
const corsOptions = {
origin: 'https://askmu.live', // Strict origin
credentials: true, // Allow cookies
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type']
};
app.use(cors(corsOptions));
Security Headers (Helmet)
import helmet from 'helmet';
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
frameguard: {
action: 'deny'
}
}));
Container Security
-
Non-Root User:
RUN addgroup -g 1001 nodejs && \ adduser -S chatbot -u 1001 USER chatbot -
Read-Only Filesystem: Most directories read-only
-
Resource Limits:
deploy: resources: limits: cpus: '1' memory: 512M -
Network Isolation: Backend not exposed to internet (only via nginx)
Environment Variables
Location: /root/catb/.env
Permissions: 600 (owner read/write only)
Required Variables:
NODE_ENV=production
PORT=3000
ANTHROPIC_API_KEY=sk-ant-...
SUPABASE_URL=https://...supabase.co
SUPABASE_SERVICE_KEY=eyJ...
DATABASE_URL=postgresql://postgres:...
RESEND_API_KEY=re_...
FRONTEND_URL=https://askmu.live
Security Practices:
- Never commit
.envto git (.gitignore) - Use service role keys for backend (not anon keys)
- Rotate keys periodically
- Audit access logs
Firewall Configuration
UFW Rules:
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw enable
API Reference
Authentication Endpoints
POST /session/create
Create authenticated session with email.
Request:
{
"email": "user@example.com"
}
Response (200):
{
"sessionToken": "a1b2c3...",
"expiresAt": "2025-10-02T18:30:00.000Z",
"sessionId": 171,
"userId": 425,
"isNewUser": false,
"profiles": {
"userProfile": {
"full_name": "Jane Doe",
"timezone": "America/New_York"
},
"catProfile": {
"cat_name": "Luna",
"cat_age": 3,
"cat_breed": "Domestic Shorthair"
}
}
}
Error Responses:
400: Invalid email format500: Database error
POST /auth/request-invite
Request magic link via email.
Request:
{
"email": "user@example.com"
}
Response (200):
{
"success": true,
"message": "Check your email for the invitation link"
}
GET /auth/verify
Verify magic link token.
Query Parameters:
token: Magic link token (64 characters)
Response:
- Redirects to frontend with sessionToken
- Error page if token invalid/expired
Chat Endpoints
POST /chat
Main chat endpoint for user messages.
Authentication: Required (sessionToken in body)
Request:
{
"message": "My cat has been vomiting",
"sessionToken": "a1b2c3..."
}
Response (200):
{
"reply": "I'm sorry to hear Luna isn't feeling well. How long has the vomiting been going on?",
"timestamp": "2025-10-01T18:30:00.000Z",
"sessionActive": true,
"usage": {
"input_tokens": 142,
"output_tokens": 183,
"estimated_cost": "0.000264"
}
}
Error Responses:
400: Missing message or invalid format401: Invalid or expired session429: Rate limit exceeded500: Server error
Rate Limit: 10 requests per minute
Health Check
GET /health
System health check (no authentication required).
Response (200):
{
"status": "healthy",
"timestamp": "2025-10-01T18:30:00.000Z",
"service": "catb-backend",
"database": {
"connected": true,
"status": "operational"
},
"anthropic": {
"configured": true,
"status": "ready"
},
"promptSystem": {
"status": "operational"
},
"security": {
"status": "HEALTHY",
"alerts": 0
}
}
Error Codes
| Code | Meaning | Common Causes |
|---|---|---|
| 400 | Bad Request | Missing required fields, invalid format |
| 401 | Unauthorized | Invalid/expired session token |
| 403 | Forbidden | Session expired (>24 hours) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Database error, Claude API error |
| 503 | Service Unavailable | Database connection failed |
Development & Operations
Local Development Setup
Prerequisites
- Node.js 20 LTS
- npm 10+
- PostgreSQL 15+ (optional, can use Supabase)
Backend Setup
# Clone repository
git clone <repo-url>
cd catb-backend
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Edit .env with your API keys
# Run locally
npm start
# Server runs on http://localhost:3000
Frontend Setup
cd catb-frontend
# Install dependencies
npm install
# Run development server
npm run dev
# Frontend runs on http://localhost:5173
Testing
Test Scripts
# Backend tests
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
# Integration tests
node test/test-session-email-fix.js
node test/comprehensive-auth-test.js
Testing Without curl
Important: curl commands are denied in this environment.
Alternative: Use Node.js test scripts:
# Start local server
PORT=3002 npm start
# Run test in another terminal
node test/test-session-email-fix.js
Example Test Script:
import fetch from 'node-fetch';
const API_BASE = 'http://localhost:3002';
async function testChat() {
// Create session
const sessionRes = await fetch(`${API_BASE}/session/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'test@example.com' })
});
const { sessionToken } = await sessionRes.json();
// Send chat message
const chatRes = await fetch(`${API_BASE}/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: 'Test message',
sessionToken
})
});
const { reply } = await chatRes.json();
console.log('Reply:', reply);
}
testChat();
Deployment Procedures
Backend Deployment
# Option 1: Use deployment script
./scripts/deploy-to-vps.sh
# Option 2: Manual deployment
rsync -av --exclude 'node_modules' ./ root@89.116.170.226:/root/catb/
ssh root@89.116.170.226 << 'EOF'
cd /root/catb
docker-compose down
docker-compose build --no-cache
docker-compose up -d
EOF
Critical: Always rebuild Docker images after code changes:
# ❌ WRONG - doesn't pick up code changes
docker-compose restart
# ✅ CORRECT - rebuilds with fresh code
docker-compose down && docker-compose build --no-cache && docker-compose up -d
Frontend Deployment
# Build and deploy frontend
cd ~/dev/catb-frontend/
npm run build
# Transfer to VPS
rsync -av --exclude 'node_modules' --exclude '.git' \
./ root@89.116.170.226:/root/catb-frontend/
# Rebuild container on VPS
ssh root@89.116.170.226 << 'EOF'
cd /root/catb-frontend
docker stop catb-frontend
docker rm catb-frontend
docker build -t catb-frontend . --no-cache
docker run -d --name catb-frontend --restart unless-stopped \
-p 127.0.0.1:3001:80 catb-frontend
EOF
Monitoring & Logging
View Logs
# Backend logs
ssh root@89.116.170.226 "docker logs catb-api --tail 100"
ssh root@89.116.170.226 "docker logs -f catb-api" # Follow
# Frontend logs
ssh root@89.116.170.226 "docker logs catb-frontend --tail 100"
# Nginx logs
ssh root@89.116.170.226 "tail -f /var/log/nginx/access.log"
ssh root@89.116.170.226 "tail -f /var/log/nginx/error.log"
Container Status
# Check all containers
ssh root@89.116.170.226 "docker ps -a"
# Check specific container
ssh root@89.116.170.226 "docker inspect catb-api"
Common Troubleshooting
Issue: Port Binding Conflict
Error: bind: address already in use
Solution: Remove port 80/443 from docker-compose.yml (nginx handles these):
ports:
- "127.0.0.1:3000:3000" # ✅ Correct
# - "80:80" # ❌ Remove this
Issue: Changes Not Appearing
Cause: Docker using cached images
Solution:
docker-compose down
docker-compose build --no-cache
docker-compose up -d
Issue: Authentication Failing
Common Mistakes:
- Token in Authorization header (should be in body)
- Using wrong field name (use
sessionToken, nottoken) - Session expired (>24 hours)
Correct Format:
// ✅ CORRECT
body: {
message: "user message",
sessionToken: "TOKEN"
}
// ❌ WRONG
headers: {
'Authorization': 'Bearer TOKEN'
}
Issue: Database Connection Error
Checks:
- Verify
.envhas correctSUPABASE_URLandSUPABASE_SERVICE_KEY - Check Supabase project status (dashboard)
- Test connection:
node scripts/test-db-connection.js - Ensure tables exist:
node scripts/execute-sql.js list
Issue: Blank Frontend Page
Symptoms: Page loads but shows blank screen, assets return HTML
Cause: Nginx misconfiguration or missing SPA routing
Solution: Ensure nginx.conf has:
location / {
proxy_pass http://127.0.0.1:3001;
try_files $uri $uri/ /index.html;
}
Database Management
Run Migrations
# Using Supabase Dashboard (recommended)
# 1. Go to SQL Editor
# 2. Copy contents of migrations/000-complete-fresh-schema.sql
# 3. Click "Run"
# Using direct PostgreSQL access (if DATABASE_URL configured)
node scripts/execute-sql.js file migrations/000-complete-fresh-schema.sql
Execute SQL Queries
# List tables
node scripts/execute-sql.js list
# Describe table
node scripts/execute-sql.js describe user_sessions
# Execute query
node scripts/execute-sql.js exec "SELECT COUNT(*) FROM messages"
Cost Structure
Monthly Costs (Production)
| Service | Tier | Cost | Notes |
|---|---|---|---|
| Hostinger VPS | Shared | $20-50 | Dual container deployment |
| Supabase | Free | $0 | 50k MAU, 500MB database |
| Resend Email | Free | $0 | 3k emails/month |
| Claude API | Pay-as-you-go | $30-100 | Depends on usage |
| Domain (askmu.live) | Namecheap | ~$1/mo | Paid annually (~$10/year) |
| SSL Certificate | Let’s Encrypt | $0 | Free auto-renewal |
| Total | - | $50-150/mo | Most variable is Claude API |
Claude API Cost Breakdown
Pricing (Sonnet 4):
- Input tokens: $3 per 1M tokens
- Output tokens: $15 per 1M tokens
Typical Chat Interaction:
- Input: ~200 tokens (conversation history + user message)
- Output: ~200 tokens (Mu response, 300 token max)
- Cost per interaction: ~$0.003-0.005
Monthly Estimates:
- 100 conversations/day: ~$15-30/month
- 500 conversations/day: ~$75-150/month
- 1000 conversations/day: ~$150-300/month
Cost Control Measures:
- Max tokens per response: 300 (hard limit)
- Conversation history pruning (last 10 messages)
- Efficient prompt design (minimal system prompt)
Scaling Considerations
Current Capacity (Single VPS):
- Concurrent users: ~50-100
- Daily conversations: ~500-1000
- Database: 500MB free tier (plenty of room)
When to Scale:
- VPS CPU consistently >70%
- Database approaching 500MB
- Email sending approaching 3k/month
- API costs exceeding budget
Scaling Options:
- Vertical: Upgrade VPS plan ($50-100/month)
- Horizontal: Add load balancer + multiple VPS instances
- Database: Upgrade Supabase to Pro ($25/month)
- Email: Upgrade Resend to paid tier ($20/month for 50k emails)
Appendix
Quick Reference
Production URLs:
- Frontend: https://askmu.live/
- API: https://askmu.live/api/
- Health: https://askmu.live/api/health
SSH Access:
ssh root@89.116.170.226
Common Commands:
# Restart backend
ssh root@89.116.170.226 "cd /root/catb && docker-compose restart"
# Rebuild backend
ssh root@89.116.170.226 "cd /root/catb && docker-compose down && docker-compose build --no-cache && docker-compose up -d"
# View logs
ssh root@89.116.170.226 "docker logs catb-api --tail 100"
# Check health
# Note: curl commands denied - use browser or test scripts
Environment Files:
- Backend:
/root/catb/.env - Frontend: Build-time only (Vite)
Recent Updates
October 2025:
- ✅ Session-email association fix (removed legacy fallback)
- ✅ ProfileService integration with LangChain
- ✅ Early profiling enabled (2-message threshold)
- ✅ Direct PostgreSQL access configured
- ✅ Test suite reorganization
September 2025:
- ✅ Express 5.1.0 upgrade (security remediation)
- ✅ Local asset deployment (replaced CDN)
- ✅ Enhanced pattern detection system
- ✅ Smart deployment system
- ✅ Feedback collection system
Support
For issues or questions:
- Check logs:
docker logs catb-api - Review health endpoint: https://askmu.live/api/health
- Check database connection:
node scripts/test-db-connection.js - Verify environment variables in
/root/catb/.env
Document Version: 1.0 Last Updated: October 1, 2025 System Status: ✅ Fully Operational
3 - CatBot Technical Architecture Specifications
Executive Summary
Pet health triage chatbot using freemium model with Anthropic LLM integration. Focus on ethical anxiety management through practical competence building.
System Architecture Overview
High-Level Architecture
Details
[Frontend] → [API Gateway] → [Application Layer] → [LLM Service] → [Anthropic API]
↓ ↓ ↓ ↓
[CDN/Media] → [Load Balancer] → [Database Layer] → [Cache Layer]
Technology Stack
- Frontend: React/Next.js with TypeScript
- Backend: Node.js with Express or Python with FastAPI
- Database: PostgreSQL (primary), Redis (cache/sessions)
- LLM Integration: Anthropic Claude API
- Media Storage: AWS S3 or Cloudflare R2
- Infrastructure: Docker containers on AWS/GCP
- Monitoring: DataDog, Sentry for error tracking
Data Architecture
Database Schema Design
Users Table
Details
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
subscription_tier VARCHAR(50) DEFAULT 'free',
subscription_expires_at TIMESTAMP,
data_retention_consent BOOLEAN DEFAULT false,
last_active TIMESTAMP
);
Cat Profiles Table
Details
CREATE TABLE cat_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
age_months INTEGER,
breed VARCHAR(100),
weight_kg DECIMAL(4,2),
medical_history JSONB,
current_medications JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Conversations Table
Details
CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
cat_id UUID REFERENCES cat_profiles(id),
session_id VARCHAR(255),
triage_outcome VARCHAR(50), -- emergency, urgent, routine, monitor
symptoms_reported JSONB,
recommendations_given JSONB,
follow_up_scheduled TIMESTAMP,
vet_visit_occurred BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP -- for data retention
);
Messages Table
Details
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL, -- user, assistant, system
content TEXT NOT NULL,
metadata JSONB, -- tokens used, response time, etc.
created_at TIMESTAMP DEFAULT NOW()
);
Media Attachments Table
Details
CREATE TABLE media_attachments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
message_id UUID REFERENCES messages(id),
file_type VARCHAR(50), -- image, video
file_url VARCHAR(500),
file_size_bytes INTEGER,
analysis_results JSONB, -- AI-generated descriptions
created_at TIMESTAMP DEFAULT NOW()
);
Data Flow Architecture
Request Processing Flow
- User Input → API Gateway (rate limiting, auth)
- Session Management → Redis lookup/creation
- Context Building → Fetch cat profile + conversation history
- LLM Preparation → Structure prompt with context
- Anthropic API Call → Send structured request
- Response Processing → Parse, validate, store response
- Client Response → Return formatted response + metadata
Data Retention Strategy
- Free Users: 48-hour conversation retention
- Premium Users: Full history retention with user control
- Media Files: 30-day retention (free), unlimited (premium)
- Analytics Data: Anonymized, indefinite retention
LLM Integration Architecture
Anthropic API Integration
Prompt Engineering Structure
Details
SYSTEM_PROMPT_TEMPLATE = """
You are a professional pet health triage assistant specializing in cats.
CONTEXT:
Cat Profile: {cat_profile}
Medical History: {medical_history}
Current Conversation: {conversation_summary}
GUIDELINES:
1. Provide practical, actionable guidance
2. Clear urgency assessment (emergency/urgent/routine/monitor)
3. Suggest specific documentation to help veterinarians
4. Offer appropriate reassurance through competence building
5. Never provide definitive diagnosis - always recommend veterinary consultation
RESPONSE FORMAT:
- Urgency Level: [level]
- Immediate Actions: [numbered list]
- Documentation Suggestions: [what to observe/record]
- Veterinary Recommendation: [timing and type]
- Follow-up Guidance: [what to monitor]
"""
Conversation State Management
Details
class ConversationContext:
def __init__(self, conversation_id):
self.conversation_id = conversation_id
self.cat_profile = self.load_cat_profile()
self.message_history = self.load_recent_messages()
self.session_metadata = self.load_session_data()
def build_prompt(self, user_message):
context = {
'cat_profile': self.cat_profile,
'medical_history': self.get_relevant_history(),
'conversation_summary': self.summarize_conversation(),
'user_message': user_message
}
return SYSTEM_PROMPT_TEMPLATE.format(**context)
def process_response(self, llm_response):
# Parse structured response
# Extract triage decision
# Store recommendations
# Update conversation state
pass
Cost Optimization Strategies
Response Caching System
Details
class ResponseCache:
def __init__(self, redis_client):
self.redis = redis_client
self.cache_ttl = 3600 # 1 hour
def get_cache_key(self, symptoms, cat_profile_hash):
# Generate hash of symptoms + basic cat info
return f"response:{hash(symptoms)}:{cat_profile_hash}"
def should_cache_response(self, urgency_level):
# Cache routine responses, not emergencies
return urgency_level in ['routine', 'monitor']
Token Usage Optimization
- Conversation summarization after 10+ exchanges
- Context pruning for long conversations
- Batch processing for multiple questions
- Response streaming for better UX
Security & Privacy Architecture
Data Protection Measures
- Encryption at Rest: AES-256 for database
- Encryption in Transit: TLS 1.3 for all communications
- API Security: Rate limiting, JWT authentication
- Data Anonymization: Hash personal identifiers for analytics
Privacy Compliance
- Data Minimization: Collect only necessary information
- User Control: Data export, deletion on request
- Consent Management: Granular permissions for data use
- Audit Logging: Track data access and modifications
Error Handling & Fallbacks
Details
class LLMService:
async def get_triage_response(self, prompt, context):
try:
response = await self.anthropic_client.complete(prompt)
return self.parse_structured_response(response)
except AnthropicAPIError as e:
if e.status_code == 429: # Rate limit
return self.get_cached_fallback(context)
elif e.status_code >= 500: # Server error
return self.get_emergency_fallback()
else:
raise
except Exception as e:
logger.error(f"Unexpected error: {e}")
return self.get_safe_fallback()
Monitoring & Analytics
Key Metrics to Track
- Usage Metrics: Sessions/day, messages/session, user retention
- Quality Metrics: Triage accuracy, user satisfaction scores
- Business Metrics: Conversion rate (free→premium), revenue per user
- Technical Metrics: API response times, error rates, cache hit rates
Logging Strategy
Details
LOGGING_CONFIG = {
'conversation_events': {
'conversation_started',
'triage_provided',
'emergency_detected',
'vet_referral_made',
'follow_up_scheduled'
},
'business_events': {
'user_upgraded',
'subscription_renewed',
'feature_accessed'
},
'technical_events': {
'api_call_made',
'cache_hit',
'error_occurred'
}
}
Deployment Architecture
Infrastructure Components
- Application Servers: Auto-scaling container groups
- Database: Primary/replica PostgreSQL setup
- Cache Layer: Redis cluster for session management
- CDN: Cloudflare for static assets and media
- Load Balancer: Application-level load balancing
CI/CD Pipeline
- Code Commit → GitHub/GitLab
- Automated Testing → Unit, integration, end-to-end tests
- Security Scanning → Dependency vulnerabilities, secrets detection
- Staging Deployment → Automated deployment to staging
- Production Deployment → Manual approval + blue-green deployment
Backup & Disaster Recovery
- Database Backups: Daily automated backups with 30-day retention
- Media Backups: Cross-region replication
- Application Recovery: Infrastructure as code for rapid rebuilding
- Data Export: User data export functionality for compliance
Learning Resources & Implementation Guide
Core Technologies
- Node.js/Express: Express.js Documentation
- PostgreSQL: PostgreSQL Official Docs
- Redis: Redis Documentation
- Docker: Docker Getting Started
LLM Integration
- Anthropic API: Anthropic Documentation
- Prompt Engineering: Claude Prompt Engineering Guide
- LLM Best Practices: Research papers on conversational AI systems
Security & Compliance
- OWASP Security Guidelines: OWASP Top 10
- Data Privacy: GDPR compliance guides, privacy by design principles
- API Security: JWT implementation, rate limiting strategies
Business & Analytics
- SaaS Metrics: Cohort analysis, customer lifetime value calculation
- A/B Testing: Statistical significance testing, experiment design
- User Experience: Conversational interface design principles
Implementation Phases
Phase 1: MVP (4-6 weeks)
- Basic conversation interface
- Simple triage logic
- Free tier functionality
- Core database schema
Phase 2: Enhanced Features (6-8 weeks)
- Premium subscription system
- Advanced triage algorithms
- Media upload capability
- User profiles and cat management
Phase 3: Business Features (4-6 weeks)
- Vet referral system
- Analytics dashboard
- Automated follow-up system
- Advanced caching and optimization
Phase 4: Scale & Optimize (Ongoing)
- Performance optimization
- Advanced analytics
- A/B testing framework
- Additional monetization features
Risk Assessment & Mitigation
Technical Risks
- Anthropic API Limitations: Implement caching and fallback responses
- Scaling Challenges: Design for horizontal scaling from start
- Data Loss: Comprehensive backup and replication strategy
Business Risks
- Liability Concerns: Clear disclaimers, professional insurance
- Regulatory Changes: Monitor pet health app regulations
- Competition: Focus on unique value proposition and user experience
Operational Risks
- User Safety: Robust emergency detection and escalation
- Data Breaches: Security-first architecture and regular audits
- Service Reliability: High availability design and monitoring
4 - MVP high level description
Catb is a chatbot helping cat owners understand their cats behavior so they can build a deeper bond with them and make them happy.
Catb asks discovery questions about owners’ cats and provides explanations and guidance.
The call to action can range from adapting their interactions or home setting to help with their pets reach optimal mental health.
Catb acts as a informed friend that soothes the owners’s anxiety while providing qualified guidance.
Goal
The MVP is meant for internal testing, it’s a website allowing interactions with an LLM.
The LLM will allow users to have conversations about their cats’ behavior, and get responses helping them understand their cats’ behavior and communication and what’s the best course of actions.
private
- private url
- no login
Limited data processing
- Only logs interactions for analysis
Not commercial
- No affiliated links
Effective
- Give proper guidance
- Asks questions to assess what the behavioral issue might be, or the misunderstanding from the user’s end.
- Only answers when enough answers are provided
- Helps owners understand their cat’s behavior and the best response if an issue is identified.
Uses Claude’s API
The interactions with the model are scoped down to cats’ behavior thanks to a single, dedicated system prompt.
Compliant with legal frameworks
- Always mentions at the end of the conversation that:
- It is an LLM and can make mistakes
- It is not a substitute for a certified veterinarian
Ethical
- No sycophantic/complacent responses
- Catb be will tell the objective truths about the owners’ cat issues
- Example: if the cat demonstrates stress because of the owner’ behavior, Catb will say so, although in diplomatic terms.
- Catb be will tell the objective truths about the owners’ cat issues
Sources from non-biased docs
- Provides links to 3 sources per final answer
- no .com domains
- no blogs
- publicly accessible peer-reviewed papers
- vets websites and vets info sources
Alleviates end-users anxiety about their pets
-
Acts as an informed friend
-
Reassures the owner if the problem doesn’t require medical attention
5 - Mu Prompt Management Framework
Mu Prompt Management Framework
Table of Contents
- Overview
- System Architecture
- Core Components
- LangChain User Profiling
- Context Analysis
- Progressive Discovery Protocol
- Template System
- Prompt Generation Flow
- Adaptive Response System
- Emergency Detection
- Integration with Claude
- Development Guide
Overview
What is the Mu Prompt System?
The Mu Prompt System is a sophisticated dynamic prompt generation framework that powers the Ask Mü cat health chatbot. Unlike static prompts, every response is generated from a fresh analysis of:
- User communication patterns (via LangChain AI profiling)
- Conversation context (symptoms, cat profile, urgency)
- Conversation phase (greeting → symptom gathering → assessment)
- User traits (anxiety level, experience, preferred style)
Key Innovation: Progressive Discovery Protocol
- Maximum 2 questions per response
- Context-aware: Analyzes existing information before asking
- Urgency-sensitive: Emergency symptoms prioritized
- Adaptive tone: Matches user’s communication style
Production Status
- Status: ✅ Fully Operational
- Deployed: https://askmu.live
- Model: Claude Sonnet 4
- Version: Mu Prompt System v3 with LangChain
- Last Update: October 2025 (Early profiling enabled)
Design Goals
- Empathy-First: Understand user’s emotional state and adapt tone
- Efficient Discovery: Gather critical information without overwhelming
- Safety-Conscious: Detect emergencies and escalate appropriately
- Personalized: Adapt to each user’s communication style and experience
- Context-Aware: Build on previous interactions, avoid redundancy
System Architecture
High-Level Architecture
User Message
│
▼
┌────────────────────────────────────────────────────────┐
│ Mu Prompt System │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 1. Conversation Context Analyzer │ │
│ │ - Extract cat profile (name, age, breed) │ │
│ │ - Detect symptoms and urgency │ │
│ │ - Assess anxiety level │ │
│ │ - Identify experience level │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 2. LangChain User Profiler (2+ messages) │ │
│ │ - Communication style analysis │ │
│ │ - Personality profile matching │ │
│ │ - Confidence level detection │ │
│ │ - Learning preference identification │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 3. Conversation Memory System │ │
│ │ - Retrieve conversation history │ │
│ │ - Update context in database │ │
│ │ - Track conversation phases │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 4. Template Engine │ │
│ │ - Load PromptL templates │ │
│ │ - Interpolate context variables │ │
│ │ - Apply conditional sections │ │
│ │ - Assemble final prompt │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
└──────────────────────┼──────────────────────────────────┘
│
▼
Dynamic System Prompt
│
▼
Claude Sonnet 4 API (300 token max)
│
▼
Empathetic, Adaptive Response
Component Interaction
┌─────────────────┐
│ User Message │
└────────┬────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ MuPromptSystem.generateDynamicPrompt() │
│ │
│ 1. getConversationContext(sessionId) │
│ └─> Returns: history, catProfile, context │
│ │
│ 2. contextAnalyzer.analyze(history, message) │
│ └─> Returns: urgency, symptoms, traits │
│ │
│ 3. langchainProfiler.analyzeUserProfile() │
│ └─> Returns: style, anxiety, personality │
│ │
│ 4. memorySystem.updateConversationContext() │
│ └─> Saves updated context to database │
│ │
│ 5. templateEngine.render(promptData) │
│ └─> Returns: final system prompt │
└──────────────────────┬──────────────────────────┘
│
▼
System Prompt for Claude
Core Components
1. MuPromptSystem (Orchestrator)
File: lib/mu-prompt-system.js
Purpose: Main orchestration class that coordinates all components to generate dynamic prompts.
Key Features:
- Integrates all subsystems (context, profiling, memory, templates)
- Manages early profiling (2-message threshold)
- Handles fallback when LangChain unavailable
- Logs profiling status and decisions
Initialization:
const promptSystem = new MuPromptSystem(
supabaseClient,
anthropicApiKey,
{ earlyProfiling: true } // Enable 2-message profiling
);
Main Method:
const promptData = await promptSystem.generateDynamicPrompt(
sessionId,
userMessage
);
// Returns: Complete data structure for template rendering
2. ConversationContextAnalyzer
File: lib/conversation-context-analyzer.js
Purpose: Analyzes messages to extract actionable context (symptoms, urgency, traits).
Analysis Dimensions:
| Dimension | Values | Purpose |
|---|---|---|
| Conversation Phase | initial, context_building, detail_gathering, assessment, guidance | Determines appropriate response type |
| Urgency Level | emergency, urgent, routine | Prioritizes response content |
| Anxiety Level | low, moderate, high, panic | Adjusts empathy and tone |
| Experience Level | first-time, beginner, experienced | Adjusts complexity |
| Communication Style | emotional, factual, low-literacy | Matches response style |
| Emotional State | calm, concerned, worried, panicked | Fine-tunes empathy |
Keyword Detection:
{
emergency: [
'trouble breathing', 'gasping', 'blue gums',
'unconscious', 'seizure', 'severe bleeding',
'collapsed', 'paralyzed'
],
urgent: [
'not eating', 'vomiting', 'diarrhea',
'lethargy', 'hiding', 'blood', 'pain'
],
routine: [
'scratching', 'grooming', 'sleeping more',
'different behavior'
]
}
Cat Profile Extraction:
{
name: /(?:my cat|his name|her name is|called)\s+(\w+)/i,
age: /(\d+)\s*(?:years?|months?)\s*old/i,
breed: /(persian|siamese|maine coon|tabby|calico)/i,
gender: /\b(he|she|male|female|boy|girl)\b/i
}
3. ConversationMemorySystem
File: lib/conversation-memory-system.js
Purpose: Database-backed persistence for conversation context.
Database Operations:
// Retrieve context
const context = await memorySystem.getConversationContext(sessionId);
// Returns: { catProfile, symptoms, history, phase, ... }
// Update context
await memorySystem.updateConversationContext(sessionId, {
catProfile: { name: 'Luna', age: 3 },
symptoms: ['vomiting', 'lethargy'],
anxietyLevel: 'high',
conversationPhase: 'symptom_gathering'
});
Context Storage:
- Table:
conversation_context - Indexed by:
session_id - Includes: cat profile, symptoms, user traits, phase, question count
Phase Management:
const maxQuestions = memorySystem.getMaxQuestionsForPhase(phase);
// initial: 2 questions
// context_building: 2 questions
// detail_gathering: 1 question (already have context)
// assessment: 0 questions (provide guidance)
4. SimpleTemplateEngine
File: lib/simple-template-engine.js
Purpose: Processes PromptL templates with variable interpolation.
Template Location: prompts/ directory
Syntax:
# Variable interpolation
{{catProfile.name}}
# Conditional sections
{{#if urgencySignals.emergency}}
EMERGENCY PROTOCOL ACTIVATED
{{/if}}
{{#unless catProfile.name}}
Ask for cat's name
{{/unless}}
# Loops
{{#each symptoms}}
- {{this}}
{{/each}}
Rendering:
const prompt = await templateEngine.render('base-prompt', {
catProfile: { name: 'Luna', age: 3 },
urgencySignals: { emergency: [], urgent: ['vomiting'] },
anxietyLevel: 'high'
});
LangChain User Profiling
Overview
File: lib/langchain/langchain-user-profiler.js
Purpose: AI-powered semantic analysis of user communication patterns using Claude Sonnet 4.
Activation: Starts at 2nd user message (early profiling enabled October 2025)
Previous Threshold: 3rd message (before October 2025 update)
Why Early Profiling?
- Faster personalization (one message sooner)
- Better first impressions (adapt tone earlier)
- Improved user experience for anxious users
Profiling Dimensions
1. Communication Style
| Style | Description | Response Adaptation |
|---|---|---|
| emotional | Seeks empathy and support | Warm, reassuring tone; emotional validation |
| factual | Wants direct information | Concise, evidence-based responses |
| low-literacy | Uses simple language | Plain language, short sentences, avoid jargon |
2. Anxiety Level
| Level | Indicators | Response Adaptation |
|---|---|---|
| low | Calm, routine inquiry | Standard empathetic tone |
| moderate | Some concern | Extra reassurance |
| high | Worried, multiple questions | High empathy, structured guidance |
| panic | “HELP!”, “emergency”, excessive punctuation | Immediate calm-down, clear next steps |
3. Experience Level
| Level | Indicators | Response Adaptation |
|---|---|---|
| first-time | “never had a cat”, “new owner” | Detailed explanations, extra context |
| beginner | Basic questions, uncertainty | Moderate detail, encouraging |
| experienced | Mentions other cats, vet visits | Higher complexity, less hand-holding |
4. Preferred Response Style
| Style | Description |
|---|---|
| concise | Brief, to-the-point answers |
| detailed | Comprehensive explanations with background |
5. Confidence Level
| Level | Description |
|---|---|
| confident | Trusts their judgment, wants validation |
| uncertain | Second-guessing, needs guidance |
| overwhelmed | Feeling lost, needs structured support |
| building | Growing confidence, needs reinforcement |
6. Learning Preference
| Preference | Adaptation |
|---|---|
| visual | Use analogies and examples |
| analytical | Provide logical reasoning and evidence |
| practical | Focus on actionable steps |
| contextual | Give background and situational understanding |
Personality Profiles
The system matches users to personality archetypes for tone guidance:
File: lib/langchain/personality-profiles.js
Profiles:
-
Anxious First-Timer
- High anxiety + low experience
- Needs: Calm reassurance, step-by-step guidance
- Tone: Gentle, patient, structured
-
Concerned Experienced Owner
- Moderate anxiety + high experience
- Needs: Validation, differential diagnosis
- Tone: Respectful, collaborative
-
Calm Information Seeker
- Low anxiety + factual style
- Needs: Direct facts, evidence
- Tone: Professional, concise
-
Panicked Emergency
- Panic level + emergency keywords
- Needs: Immediate clear instructions
- Tone: Authoritative, calming, directive
-
Building Confidence
- Improving confidence + beginner
- Needs: Positive reinforcement
- Tone: Encouraging, supportive
Analysis Process
LangChain Invocation:
const profile = await langchainProfiler.analyzeUserProfile(
conversationHistory,
currentMessage
);
Analysis Prompt (sent to Claude Sonnet 4):
You are an expert at analyzing communication patterns to understand
user profiles for adaptive AI responses about cat behavior.
Analyze this cat owner's communication style and needs based on
their messages:
MESSAGE COUNT: 2
IMPORTANT: This is early analysis with only 2 message(s). Focus on
clear indicators while being conservative about confidence levels.
USER MESSAGES:
"""
Help! My cat Luna has been vomiting all morning. I'm really scared,
is this serious? She's only 3 years old.
I've tried giving her water but she won't drink. Should I take her
to the vet right away?
"""
ANALYSIS FRAMEWORK:
[Communication style, anxiety level, experience level descriptors...]
Respond with a JSON profile analysis.
Response Structure:
{
"communicationStyle": "emotional",
"anxietyLevel": "high",
"experienceLevel": "beginner",
"preferredResponseStyle": "detailed",
"confidenceLevel": "uncertain",
"learningPreference": "practical"
}
Confidence Scoring:
{
overall: 0.75, // Confidence in the entire profile
factorScores: {
communicationStyle: 0.9, // Very clear emotional language
anxietyLevel: 0.95, // "Help!", "scared", exclamation
experienceLevel: 0.6, // Limited data, conservative estimate
// ...
}
}
Personality Selection:
const personality = selectPersonality(profile);
// Returns: "Anxious First-Timer"
const instructions = getPersonalityInstructions(personality);
// Returns: Detailed guidance for response tone and structure
Fallback Mechanism
If LangChain analysis fails (API error, timeout):
getFallbackProfile() {
return {
profile: {
communicationStyle: 'emotional',
anxietyLevel: 'moderate',
experienceLevel: 'beginner',
preferredResponseStyle: 'concise',
confidenceLevel: 'uncertain',
learningPreference: 'practical'
},
confidence: { overall: 0.5 },
personalityProfile: {
name: 'Default Concerned Owner',
description: 'Fallback profile when analysis unavailable'
}
};
}
Progressive Discovery Protocol
Core Principle
Maximum 2 Questions Per Response
This is the fundamental constraint of the Mu system, designed to:
- Avoid overwhelming worried pet owners
- Maintain conversation flow
- Build trust through attentive listening
- Respect user’s emotional state
Question Budget System
Phase-Based Limits:
{
initial: 2, // Greeting, get basic context
context_building: 2, // Gather cat profile + symptoms
detail_gathering: 1, // Already have context, refine details
assessment: 0, // Provide guidance, no more questions
guidance: 0 // Final recommendations
}
Question Prioritization
Priority Order:
-
Emergency Verification (if emergency symptoms)
- “Have you contacted a veterinarian?”
- “Is [cat] still breathing normally?”
-
Timeline (if missing)
- “How long has this been going on?”
- “When did you first notice this?”
-
Severity (if unclear)
- “How often is this happening?”
- “Is it getting worse?”
-
Context (after basics covered)
- “Any recent changes in food or environment?”
- “Is [cat] eating/drinking normally?”
-
Clarification (lowest priority)
- “You mentioned [X], can you describe it more?”
Example Progressive Discovery
Message 1 (User):
“Help! My cat has been vomiting”
Mu Response (2 questions):
I’m sorry to hear your cat isn’t feeling well. Vomiting can be concerning.
To help you better:
- How long has the vomiting been going on?
- What’s your cat’s name and age?
Message 2 (User):
“Her name is Luna, she’s 3. Started this morning, maybe 4-5 times already.”
Mu Response (1 question):
Thank you for that information. I’m concerned about Luna vomiting 4-5 times this morning. This is more frequent than normal and warrants attention.
Has she been able to keep any water down, or is she vomiting everything?
[Assessment and guidance…]
Message 3 (User):
“She won’t drink at all. Just tried and she vomited again.”
Mu Response (0 questions - assessment phase):
This is concerning, and I recommend contacting your veterinarian today. Multiple vomiting episodes combined with refusing water can lead to dehydration…
[Detailed guidance, no questions]
Emergency Detection
Emergency Symptom Keywords
Immediate Veterinary Attention Required:
const EMERGENCY_SYMPTOMS = [
// Respiratory
'trouble breathing', 'difficulty breathing', 'gasping for air',
// Circulatory
'pale gums', 'blue gums', 'gray gums',
// Neurological
'unconscious', 'seizure', 'convulsing',
// Trauma
'severe bleeding', 'hit by car',
// Mobility
'can\'t walk', 'paralyzed', 'collapsed'
];
Emergency Protocol
When Emergency Detected:
⚠️ EMERGENCY PROTOCOL ACTIVATED ⚠️
SYMPTOMS DETECTED: {{#each urgencySignals.emergency}}{{this}}, {{/each}}
IMMEDIATE RESPONSE REQUIRED:
CRITICAL INSTRUCTIONS:
1. Contact emergency veterinary clinic immediately
2. If after hours, contact 24-hour emergency vet
3. Do NOT wait to see if it improves
4. Transport safely - avoid unnecessary movement
TIME IS CRITICAL. Please act now.
Response Characteristics:
- Directive tone: Clear commands, not suggestions
- Urgent but not panicking: Calm authority
- Action-focused: Immediate steps only
- Minimal questions: Ask ONLY “Have you contacted a vet?”
- Short sentences: Easy to process under stress
Integration with Claude
API Configuration
Model: claude-sonnet-4-20250514
Temperature: 0.7 (balanced creativity and consistency)
Max Output Tokens: 300 (cost control + concise responses)
System Prompt
Structure:
{
model: 'claude-sonnet-4-20250514',
max_tokens: 300,
temperature: 0.7,
system: generatedPrompt, // Dynamic prompt from template
messages: conversationHistory
}
Token Budget:
System Prompt: ~1500 tokens
Conversation History (10 messages): ~1000 tokens
Current User Message: ~100 tokens
---
Total Input: ~2600 tokens
Max Output: 300 tokens
Total per request: ~2900 tokens
Cost: ~$0.003 per interaction
Development Guide
Adding New Templates
1. Create Template File:
touch prompts/new-scenario.promptl
2. Define Template:
# New Scenario Template
You are Mu, helping with [specific scenario].
CONTEXT:
{{catProfile.name}} is experiencing {{primarySymptom}}.
[Template content...]
3. Register in Template Engine:
// lib/simple-template-engine.js
const TEMPLATES = {
'base-prompt': 'base-prompt.promptl',
'new-scenario': 'new-scenario.promptl' // Add here
};
Testing Prompt Variations
Enable Detailed Logging:
// Set environment variable
LOG_PROMPT_GENERATION=true npm start
Log Output:
🔍 LangChain User Profiler: Performing semantic analysis...
🧠 LangChain profile analysis completed (2 messages): {
style: 'emotional',
anxiety: 'high',
experience: 'beginner',
confidence: 0.75,
personality: 'Anxious First-Timer'
}
Example Scenarios
Scenario 1: Anxious First-Time Owner
User Message:
“HELP!! My cat isn’t eating and I don’t know what to do! Is she dying??”
Context Analysis:
{
anxietyLevel: 'panic',
experienceLevel: 'first-time',
communicationStyle: 'emotional'
}
Mu Response:
First, take a deep breath. Not eating for a short time doesn’t always mean something serious, but I can see how worried you are, and I’m here to help.
To better understand what’s happening:
- How long has it been since your cat last ate?
- What’s your cat’s name and age?
You’re doing the right thing by reaching out. We’ll figure this out together.
Scenario 2: Emergency Situation
User Message:
“My cat just collapsed and won’t get up! Her gums look pale!”
Emergency Protocol Activated:
Mu Response:
⚠️ THIS IS AN EMERGENCY ⚠️
Your cat needs immediate veterinary attention. DO NOT WAIT.
IMMEDIATE ACTIONS:
- Call your emergency vet or 24-hour clinic NOW
- Keep your cat warm with a light blanket
- Minimize movement - transport carefully
Have you contacted a veterinary clinic yet?
Conclusion
The Mu Prompt Management Framework represents a sophisticated, adaptive system that:
- Analyzes user communication patterns with AI-powered LangChain profiling
- Tracks conversation context across multiple dimensions
- Adapts response style based on user needs
- Prioritizes information gathering through progressive discovery
- Templates dynamic prompts for consistent responses
- Integrates seamlessly with Claude Sonnet 4
Production Impact:
- More personalized user experiences
- Faster emergency detection
- Better information gathering efficiency
- Higher user satisfaction
Document Version: 1.0 Last Updated: October 1, 2025 System Status: ✅ Production (https://askmu.live) Framework Version: Mu Prompt System v3 with LangChain
6 - Concepts
This page will contain all the jargon we’ll use for catb. As the project grows and the contributors multiply, it’ll save time with exchanges and onboarding