Skip to main content
The post-call processing service handles asynchronous processing of completed calls, including transcript assembly, AI-powered summarization, and email notifications.

Architecture

The service uses a queue-based architecture with the following components:

Processing Flow

1. Enqueue Request

Calls are enqueued via the /api/v1/process endpoint. The system:
  • Validates call_id and tenant_id
  • Checks if the call is already completed (idempotent)
  • Sets MongoDB status to pending
  • Adds job to in-memory queue

2. Worker Processing

The background worker (WorkerLoop) continuously processes jobs:
  1. Dequeue: Removes job from queue and marks as in-progress
  2. Fetch Data: Retrieves transcript and metadata from MongoDB
  3. Assemble Transcript: Reconstructs ordered transcript from ASR chunks
  4. Generate Summary: Calls OpenAI API for non-empty transcripts
  5. Send Email: Delivers summary to configured recipients
  6. Update Status: Marks call as completed or failed
Source: src/apps/post_call/app/worker_loop.py:69-83

3. Transcript Assembly

Transcripts are assembled from MongoDB using linked-list ordering:
  • Items are connected via previous_item_id pointers
  • ASR chunks are joined in sequence order
  • User and assistant roles are distinguished
  • Empty transcripts (seq ≤ 2 or no content) trigger fallback flow
Source: src/apps/post_call/app/utils/transcript.py:181-237

4. AI Summarization

For non-empty transcripts, the worker:
  • Sends transcript to OpenAI with structured output schema
  • Receives PostCallSummary with:
    • One-line summary
    • Caller request
    • Key points
    • Actions to take
    • Contact information
Source: src/apps/post_call/app/worker_loop.py:429-462

5. Email Notification

Emails are sent via SMTP with:
  • HTML body containing summary and transcript
  • Subject line with tenant name and caller number
  • Configured recipient list from tenant config
  • Optional BCC for monitoring
Source: src/apps/post_call/app/worker_loop.py:464-514

Queue Management

The CallQueue class manages job lifecycle:
  • Idempotent enqueuing: Jobs already queued or in-progress are rejected
  • State tracking: Separate sets for queued_keys and in_progress_keys
  • Thread-safe: All operations protected by asyncio lock
Source: src/apps/post_call/app/call_queue.py:18-65

Retry Logic

Failed jobs are retried up to 3 times with exponential backoff:
  • Retryable errors: Network issues, timeouts, 5xx status codes
  • Non-retryable errors: Validation errors, 4xx status codes (except 429)
  • Backoff: min(2^(attempt-1), 8) seconds
  • Terminal failure: Status set to failed after max attempts
Source: src/apps/post_call/app/worker_loop.py:85-152

Status States

Calls progress through the following states:
StatusDescription
pendingQueued for processing
processingCurrently being processed (internal)
completedSuccessfully processed and email sent
failedProcessing failed after max retries
Source: src/models/utils/enums.py:4-8

Configuration

The service requires:
  • MongoDB: Collections for transcripts, metadata, and tenant configs
  • OpenAI API: For structured summarization
  • SMTP: For email delivery
  • Tenant Config: Display name and recipient list per tenant
Source: src/apps/post_call/main.py:18-41

Next Steps

Process Endpoint

Trigger post-call processing for a specific call

Build docs developers (and LLMs) love