Docs / Raw

Admin Panel Integration Guide

Sourced from docs/admin/ADMIN_PANEL_INTEGRATION_GUIDE.md

Edit on GitHub

Admin Panel Integration Guide

This guide covers the VoiceAssist admin panel integration with the main web app, including cross-app navigation, real-time event streaming, and voice session monitoring.

Admin Panel URL: https://admin.asimo.io

Table of Contents

  1. Overview
  2. Cross-App Navigation
  3. Conversations Management
  4. Clinical Contexts & PHI
  5. Voice Monitor & TT Pipeline
  6. Real-Time Events
  7. API Reference
  8. Configuration

Overview

The admin panel provides a centralized interface for monitoring and managing the VoiceAssist platform. Key capabilities include:

  • Conversations Management: View all user conversations with full message history
  • Clinical Contexts: Access and audit PHI data with HIPAA-compliant logging
  • Voice Monitoring: Real-time visibility into voice sessions and the Thinker-Talker pipeline
  • System Metrics: Database pools, Redis connections, and WebSocket sessions
  • Real-Time Events: Live event streaming via WebSocket with Redis pub/sub

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Admin Panel   │     │    Web App      │     │   Docs Site     │
│ admin.asimo.io  │────▶│  dev.asimo.io   │────▶│  docs.asimo.io  │
└────────┬────────┘     └────────┬────────┘     └─────────────────┘
         │                       │
         └───────────┬───────────┘
                     ▼
         ┌─────────────────────┐
         │    API Gateway      │
         │  /api/admin/panel/* │
         └──────────┬──────────┘
                    │
         ┌──────────┴──────────┐
         │                     │
    ┌────▼────┐          ┌─────▼────┐
    │ Database │          │  Redis   │
    │PostgreSQL│          │ Pub/Sub  │
    └──────────┘          └──────────┘

Cross-App Navigation

The admin panel integrates seamlessly with other VoiceAssist applications through a unified navigation system.

The navigation configuration is defined in /apps/admin-panel/src/config/externalLinks.ts:

export interface ExternalApp { id: string; name: string; url: string; description: string; icon: string; } export const externalApps: ExternalApp[] = [ { id: "web-app", name: "VoiceAssist App", url: "https://dev.asimo.io", description: "Main voice assistant application", icon: "MessageSquare", }, { id: "docs", name: "Documentation", url: "https://docs.asimo.io", description: "Technical documentation", icon: "Book", }, ];

Using the AppSwitcher Component

The AppSwitcher component provides a dropdown menu for navigating between applications:

import { AppSwitcher } from "@/components/AppSwitcher"; // In your header component <AppSwitcher currentApp="admin" />;

Environment Variables

Configure application URLs via environment variables:

VITE_WEB_APP_URL=https://dev.asimo.io VITE_DOCS_URL=https://docs.asimo.io VITE_ADMIN_URL=https://admin.asimo.io

Conversations Management

The Conversations page provides administrators with visibility into all user conversations.

Accessing Conversations

Navigate to Conversations in the admin sidebar to view:

  • All conversations across all users
  • Message count and creation time
  • Last activity timestamp
  • Conversation title and status

Conversation List API

GET /api/admin/panel/conversations

Query parameters:

  • user_id (optional): Filter by user
  • page (optional): Page number (default: 1)
  • page_size (optional): Results per page (default: 50)
  • sort_by (optional): Sort field (created_at, updated_at, message_count)
  • sort_order (optional): asc or desc

Response:

{ "conversations": [ { "id": "conv-uuid", "user_id": "user-uuid", "user_email": "user@example.com", "title": "Conversation Title", "message_count": 42, "created_at": "2025-12-01T10:00:00Z", "updated_at": "2025-12-01T15:30:00Z" } ], "total": 100, "page": 1, "page_size": 50 }

Viewing Conversation Details

GET /api/admin/panel/conversations/{conversation_id}

Returns the full conversation with all messages:

{ "id": "conv-uuid", "user_id": "user-uuid", "user_email": "user@example.com", "title": "Conversation Title", "messages": [ { "id": "msg-uuid", "role": "user", "content": "Hello, I have a question...", "created_at": "2025-12-01T10:00:00Z" }, { "id": "msg-uuid-2", "role": "assistant", "content": "I'd be happy to help...", "created_at": "2025-12-01T10:00:05Z" } ], "created_at": "2025-12-01T10:00:00Z", "updated_at": "2025-12-01T15:30:00Z" }

Clinical Contexts & PHI

The Clinical Contexts page provides HIPAA-compliant access to Protected Health Information (PHI).

PHI Access Requirements

  • All PHI access is logged with admin user ID, timestamp, and target user
  • PHI data is masked by default until explicitly revealed
  • Access requires appropriate admin role permissions

Clinical Context List

GET /api/admin/panel/clinical-contexts

Query parameters:

  • user_id (optional): Filter by user
  • has_phi (optional): Filter by PHI presence (true/false)
  • page (optional): Page number
  • page_size (optional): Results per page

Response with masked PHI:

{ "contexts": [ { "id": "ctx-uuid", "user_id": "user-uuid", "user_email": "user@example.com", "has_phi": true, "phi_masked": { "conditions": ["[REDACTED]"], "medications": ["[REDACTED]"], "allergies": ["[REDACTED]"] }, "created_at": "2025-12-01T10:00:00Z", "updated_at": "2025-12-01T15:30:00Z" } ], "total": 25, "page": 1, "page_size": 50 }

Revealing PHI

To reveal PHI data (logged for audit):

POST /api/admin/panel/clinical-contexts/{context_id}/reveal

Response includes unmasked PHI:

{ "id": "ctx-uuid", "phi": { "conditions": ["Hypertension", "Type 2 Diabetes"], "medications": ["Metformin 500mg", "Lisinopril 10mg"], "allergies": ["Penicillin"] }, "revealed_at": "2025-12-01T16:00:00Z", "revealed_by": "admin@example.com" }

Audit Logging

All PHI access events are published to the real-time event stream:

{ "type": "phi.accessed", "timestamp": "2025-12-01T16:00:00Z", "user_id": "admin-uuid", "user_email": "admin@example.com", "resource_id": "ctx-uuid", "resource_type": "clinical_context", "data": { "target_user_id": "user-uuid" } }

Voice Monitor & TT Pipeline

The Voice Monitor provides real-time visibility into voice sessions and the Thinker-Talker (TT) pipeline.

Voice Sessions Tab

View all active voice sessions:

FieldDescription
Session IDUnique WebSocket session identifier
UserEmail of connected user
Statusconnected, speaking, listening, processing
DurationTime since connection
VoiceSelected TTS voice
QualityAudio quality preset

TT Pipeline Tab

Monitor the Thinker-Talker pipeline components:

TT Sessions

Active Thinker-Talker sessions with state information:

  • Session ID: Unique TT session identifier
  • State: idle, thinking, speaking, listening, tool_executing
  • Thinker Model: Active LLM model
  • Current Tool: Currently executing tool (if any)
  • Latency: Round-trip processing time

TT Contexts

Active context windows with expiration tracking:

  • Context ID: Unique context identifier
  • Session ID: Parent TT session
  • Created: Context creation time
  • Expires: TTL expiration time
  • Size: Context token count

Quality Presets

Available audio quality configurations:

PresetSample RateBit DepthBuffer Size
high48000 Hz24-bit4096
medium44100 Hz16-bit2048
low22050 Hz16-bit1024

Analytics Tab

Voice pipeline performance metrics:

  • Tool Call Frequency: Bar chart of most-used tools
  • KB Performance: Knowledge base query latency
  • Average Latency: TT pipeline response time
  • Error Rate: Failed voice sessions percentage

API Endpoints

# Get active voice sessions GET /api/admin/panel/voice/sessions # Get TT pipeline state GET /api/admin/panel/voice/tt-sessions GET /api/admin/panel/voice/tt-contexts GET /api/admin/panel/voice/quality-presets # Get TT analytics GET /api/admin/panel/voice/tt-analytics # Cleanup expired contexts POST /api/admin/panel/voice/tt-contexts/cleanup # Disconnect a voice session POST /api/admin/panel/voice/sessions/{session_id}/disconnect

Real-Time Events

The admin panel receives real-time events via WebSocket, powered by Redis pub/sub.

WebSocket Connection

Connect to the admin WebSocket endpoint:

const ws = new WebSocket("wss://admin.asimo.io/api/admin/panel/ws");

Event Types

Event TypeDescription
session.connectedUser connected to WebSocket
session.disconnectedUser disconnected
conversation.createdNew conversation started
conversation.updatedConversation modified
message.createdNew message added
clinical_context.createdNew clinical context
clinical_context.updatedContext modified
phi.accessedPHI data revealed (audit)
phi.detectedPHI detected in message
voice.session_startedVoice session began
voice.session_endedVoice session ended
voice.session_errorVoice session error
tt.state_changedTT pipeline state change
tt.tool_calledTT tool execution
tt.context_createdTT context created
tt.context_expiredTT context expired
system.alertSystem alert notification
system.health_changedHealth status change
user.logged_inUser login
user.logged_outUser logout
user.createdNew user registered

Event Payload Format

{ "type": "admin_event", "payload": { "type": "voice.session_started", "timestamp": "2025-12-01T16:00:00Z", "user_id": "user-uuid", "user_email": "user@example.com", "session_id": "ws-session-uuid", "resource_id": "voice-session-uuid", "resource_type": "voice_session", "data": { "session_type": "realtime", "voice": "alloy" } } }

Subscribing to Events

Filter events by type:

ws.send( JSON.stringify({ type: "subscribe", payload: { event_types: ["voice.session_started", "voice.session_ended"], }, }), );

Using the React Hook

import { useRealtimeEvents } from "@/hooks/useRealtimeEvents"; function VoiceMonitor() { const { status, events, metrics, connect, disconnect } = useRealtimeEvents({ autoConnect: true, eventFilter: ["voice.session_started", "voice.session_ended"], onEvent: (event) => { console.log("New event:", event); }, onMetrics: (metrics) => { console.log("Metrics update:", metrics); }, }); return ( <div> <p>Connection: {status}</p> <p>Events received: {events.length}</p> </div> ); }

Metrics Updates

The WebSocket also receives periodic metrics:

{ "type": "metrics_update", "payload": { "active_websocket_sessions": 42, "database_pool": { "pool_size": 20, "checked_out": 5, "overflow": 0 }, "redis_pool": { "total_connections": 10, "available_connections": 8 }, "timestamp": "2025-12-01T16:00:00Z" } }

API Reference

Admin Panel Endpoints

All endpoints require admin authentication.

MethodEndpointDescription
GET/api/admin/panel/conversationsList conversations
GET/api/admin/panel/conversations/{id}Get conversation detail
GET/api/admin/panel/clinical-contextsList clinical contexts
GET/api/admin/panel/clinical-contexts/{id}Get context detail
POST/api/admin/panel/clinical-contexts/{id}/revealReveal PHI
GET/api/admin/panel/voice/sessionsList voice sessions
POST/api/admin/panel/voice/sessions/{id}/disconnectDisconnect session
GET/api/admin/panel/voice/tt-sessionsList TT sessions
GET/api/admin/panel/voice/tt-contextsList TT contexts
POST/api/admin/panel/voice/tt-contexts/cleanupCleanup contexts
GET/api/admin/panel/voice/quality-presetsGet quality presets
GET/api/admin/panel/voice/tt-analyticsGet TT analytics
WS/api/admin/panel/wsReal-time events

Authentication

All admin API requests require a valid JWT token in the Authorization header:

Authorization: Bearer <admin_jwt_token>

Error Responses

{ "detail": "Not authorized to access this resource", "status_code": 403 }

Configuration

Environment Variables

# API Gateway ADMIN_PANEL_ENABLED=true ADMIN_PANEL_CORS_ORIGINS=https://admin.asimo.io # Redis (for real-time events) REDIS_URL=redis://localhost:6379 ADMIN_EVENTS_CHANNEL=admin:events # Database DATABASE_URL=postgresql://user:pass@localhost/voiceassist # JWT JWT_SECRET=your-secret-key JWT_ALGORITHM=HS256

Redis Pub/Sub Configuration

The admin event publisher uses Redis pub/sub for broadcasting events:

from app.services.admin_event_publisher import ( AdminEventPublisher, publish_voice_session_started, publish_phi_accessed, ) # Start the publisher publisher = AdminEventPublisher.get_instance() await publisher.start() # Publish events await publish_voice_session_started( user_id="user-uuid", session_id="session-uuid", session_type="realtime", voice="alloy" )

Feature Flags

# Enable/disable admin features FEATURE_ADMIN_VOICE_MONITOR=true FEATURE_ADMIN_REALTIME_EVENTS=true FEATURE_ADMIN_PHI_ACCESS=true

Troubleshooting

WebSocket Connection Issues

  1. Check that the admin panel is properly authenticated
  2. Verify Redis is running and accessible
  3. Check for CORS configuration issues
# Test Redis connection redis-cli ping # Check Redis pub/sub redis-cli SUBSCRIBE admin:events

Missing Events

  1. Verify the event publisher is started during app initialization
  2. Check that events are being published from the source
# In main.py startup @app.on_event("startup") async def startup(): publisher = AdminEventPublisher.get_instance() await publisher.start()

PHI Access Denied

  1. Verify admin user has appropriate role
  2. Check audit log for access attempts
  3. Confirm context ID exists

Beginning of guide
End of guide