Skip to content

Analyzer

The analyzer module runs LLM-powered analysis on call transcriptions after a call ends. Two types of analyzers process every call: org analyzers (custom, user-defined) and system analyzers (platform-wide, hidden from users). Both use GPT-5 with a custom prompt to extract insights from the transcription.

Call ends → Transcription saved → analyze_call(call_id)
├─ Org Analyzers (assigned to the phone number)
│ For each: prompt + transcription → GPT-5 → save to call_analysis
└─ System Analyzers (run on every call)
For each: prompt + transcription → GPT-5 → save to system_call_analysis

Created and managed by the organization through the UI and API. Each analyzer has a custom prompt and is assigned to specific phone numbers via the phone_number_analyzer join table.

pub struct Analyzer {
pub id: Uuid,
pub name: String,
pub prompt: String, // LLM instruction for analysis
pub phone_ids: Vec<Uuid>, // Phone numbers this analyzer runs on
pub default: bool, // Auto-assign to new phone numbers
}

Example use cases: sentiment analysis, lead qualification, compliance checks, call summary generation.

Results are stored in the call_analysis table and visible in the call details UI.

Platform-level analyzers stored in the system_analyzer table. They run on every call automatically, regardless of phone number assignments. Organizations don’t see or manage these.

Results are stored in a separate system_call_analysis table.

analyze_call is the main entry point, called after a transcription is saved:

  1. Load the call record and its phone_number_id
  2. Find all org analyzers assigned to that phone number (phone_number_analyzer table)
  3. Run each org analyzer sequentially:
    • Load the analyzer’s prompt
    • Send prompt (system) + transcription (user) to GPT-5
    • Save result to call_analysis with call_id, analyzer_id, analysis_text
  4. Run all system analyzers (from system_analyzer table):
    • Same flow but results go to system_call_analysis with system_analyzer_id

All analysis goes through analyze_call_text:

pub async fn analyze_call_text(
prompt: String, // Analyzer instruction (system message)
transcription: String, // Call transcript (user message)
) -> Result<String, AppError>

Model: GPT-5 via aisdk OpenAI provider. Returns raw text output.

TableAnalyzer TypeKey Fields
call_analysisOrgcall_id, analyzer_id, analysis_text, created_at
system_call_analysisSystemcall_id, system_analyzer_id, analysis_text, created_at

All endpoints require an authenticated session and scope to the org.

RouteMethodDescription
/api/analyzersGETList all org analyzers (phone assignments not loaded)
/api/analyzers/{id}GETGet an analyzer with phone assignments
/api/analyzersPOSTCreate an analyzer with phone assignments
/api/analyzers/{id}PUTUpdate name, prompt, default flag, and phone assignments
/api/analyzers/{id}DELETEDelete an analyzer

Create and update accept AnalyzerData:

pub struct AnalyzerData {
pub name: String,
pub prompt: String,
pub phone_ids: Vec<Uuid>,
pub default: bool,
}

Phone assignment updates use a delete-all-then-reinsert strategy on phone_number_analyzer.

The create and edit forms for org analyzers use the AI Builder to generate and refine the prompt field. Instead of writing analysis instructions manually, you describe what you want in plain English and the AI produces a structured prompt.

Supported actions:

  • Generate — describe the analysis you need (e.g., “Extract sentiment, key issues, and resolution status”) and get a complete prompt with categories, output format, and edge cases
  • Edit — refine the generated prompt with 8 predefined actions (Improve, Make Concise, Add Examples, Strengthen Safety, etc.) plus free-text custom edits
  • Undo — revert the last edit

The AI Builder components (AiGenerateInstructions, InstructionPreview, AiInstructionToolbar) replace the plain textarea in both CreateAnalyzer and AnalyzerDetails components. The AiBuilderArea::Analyzer variant routes requests to 10 analyzer-specific prompt templates in src/shared/ai_builder/prompts/analyzer/.

Permission: AnalyzerCollectionPermission::Create is required to use the AI Builder for analyzers.

Analyzers are linked to phone numbers, not agents. When a call comes in on a phone number, all analyzers assigned to that number run on the transcription.

The default flag on an analyzer means it gets auto-assigned to newly purchased phone numbers (handled during the phone purchase flow in the twilio module).

src/mods/analyzer/
├── api/ # CRUD for org analyzers
├── components/ # UI: analyzer list, card, details, create form
├── types/ # Analyzer, AnalyzerData
├── utils/ # analyze_call, analyze_call_one_analyzer, analyze_call_system_analyzers, analyze_call_text
└── views/ # AnalyzerListView, AnalyzerDetailsView, CreateAnalyzerView
  • Call — analysis results are linked to calls and shown in call details
  • Phone — analyzers are assigned to phone numbers
  • Todos — todo extraction runs after analysis, also using the transcription