Callback flow
- Frontend queues task: Creates a
TaskStatusrecord in the database with statuspending - Backend processes task: Separate service at
TASK_API_URLpicks up and executes the task - Backend sends updates: POSTs progress and completion updates to the callback URL
- Frontend handles callback: Updates database and triggers result processing
Callback endpoint
The callback URL follows this pattern:Path parameters
The unique identifier for the city
The unique identifier for the council meeting
The unique identifier for the task status record
Request body
The callback sends aTaskUpdate object with the following structure:
Current task status. One of:
processing, success, errorHuman-readable description of the current processing stage
Progress percentage (0-100)
Task handler version number for tracking updates across deployments
Task-specific result data (only present when
status is success)Error message (only present when
status is error)Response
Confirmation message: “Task status updated successfully”
Example callbacks
Progress update
Success with result
Error callback
Task types
OpenCouncil supports multiple task types, each with specific request and result formats:Core pipeline tasks
These tasks are required for the main processing pipeline:- transcribe: Transcribes audio/video and identifies speakers using voiceprints
- fixTranscript: Corrects transcription errors using AI
- humanReview: Flags transcript for human review
- transcriptSent: Marks transcript as sent to external service
- summarize: Generates AI summaries and extracts subjects from discussions
Optional tasks
These tasks can run multiple times and are not part of the core pipeline:- processAgenda: Extracts structured data from meeting agenda PDFs
- generatePodcastSpec: Creates podcast scripts from meeting highlights
- generateHighlight: Generates video highlights with captions
- splitMediaFile: Splits audio/video into segments
- generateVoiceprint: Creates speaker voice embeddings for identification
- pollDecisions: Fetches and matches decisions from Diavgeia (Greek transparency portal)
Idempotency
Core pipeline tasks enforce automatic idempotency to prevent duplicate processing:- Already succeeded: If a task of the same type has already succeeded for a meeting, new requests are rejected
- Already running: If a task is currently in progress, new requests are rejected
- Force mode: Pass
force: trueto bypass idempotency and reprocess
Result processing
When a task succeeds, the callback handler:- Updates the
TaskStatusrecord with statussucceededand stores the result - Calls the task-specific result handler from the registry
- Processes and stores result data in the database (e.g., creates
SpeakerSegmentrecords for transcribe tasks) - Sends admin alert via Discord webhook
- Revalidates Next.js cache for affected meeting data
failed with error details.
Cache revalidation
Successful completion of these task types triggers Next.js cache revalidation:- summarize: Revalidates meeting lists
- processAgenda: Revalidates meeting lists
- pollDecisions: Revalidates meeting lists
city:{cityId}:meetings
Error handling
The callback endpoint handles errors gracefully:- 404: Task status record not found
- 500: Error during result processing (task marked as failed with error details)
Security
Callback URLs are automatically generated by the system and include:- Full path with city, meeting, and task IDs
- Base URL from
NEXTAUTH_URLenvironment variable - No additional authentication required (task ID serves as authorization)
Authorization: Bearer {TASK_API_KEY}.
Discord notifications
All task lifecycle events trigger Discord admin alerts:- Started: When task is queued and sent to backend
- Completed: When task succeeds and result processing completes
- Failed: When task fails or result processing errors