DDARE Docs
Backend

Socket.IO Event Contract

Real-time event payloads for chat and workflow namespaces.

Complete reference for all real-time events in the DARE platform. The backend uses python-socketio with Redis pub/sub. All payload keys are camelCase (backend applies camelize() before emission). Event names are snake_case.

Authentication

Both namespaces authenticate via the auth handshake option:

// Standard JWT auth
socket = io('/chat', { auth: { token: 'jwt_access_token' } })

// Session-based auth (public bots only, /chat namespace)
socket = io('/chat', { auth: { sessionId: 'uuid', conversationId: 'uuid' } })

/chat Namespace

Client → Server Events

subscribe_conversation

Subscribe to real-time updates for a conversation. Returns conversation history via callback.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
platformstringNoPlatform identifier

Callback response: { success: boolean, error?: string, conversationId?: string }

After subscribing, the server emits a message event with type: 'conversation_history' containing full message history.


unsubscribe_conversation

Leave a conversation room. Stops receiving updates.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID

Callback response: { success: boolean, error?: string }


send_message

Send a chat message. Triggers LLM streaming response.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
messagestringYesUser message text
active_artifact_idnumberNoCurrently open artifact (for intent detection)
(additional fields)anyNoModel config, file IDs, etc.

Callback response: { success: boolean, error?: string }


send_voice_message

Send an audio recording for transcription + LLM response.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
audiostringYesBase64-encoded audio data
audioFormatstringYesAudio format (e.g., 'webm')
languagestringNoLanguage code (default: 'auto')

Callback response: { success: boolean, error?: string, text?: string }


edit_message

Edit a previously sent message. Triggers re-generation of AI response.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
messageIdstringYesMessage ID to edit
messagestringYesNew message content

Callback response: { success: boolean, error?: string }


regenerate_response

Regenerate an AI response for a specific message.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
messageIdstringYesMessage ID to regenerate
message_idstringYesSame as messageId (legacy compat)

Callback response: { success: boolean, error?: string }


continue_artifact

Resume generation of a paused artifact.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
artifactIdnumberYesArtifact ID to continue

Callback response: { success: boolean, error?: string }


pause_artifact

Pause an in-progress artifact generation.

FieldTypeRequiredDescription
conversationIdstringYesConversation UUID
artifactIdnumberYesArtifact ID to pause

Callback response: { success: boolean, error?: string }


Server → Client Events

All server-to-client events in the /chat namespace are sent as a single message event with a type field that discriminates the payload shape.

message (type: conversation_history)

Sent immediately after subscribe_conversation. Contains full message history.

{
  type: 'conversation_history',
  conversationHistory: Message[]
}

message (type: message)

A complete message (user or assistant). Sent when a message is fully processed.

{
  type: 'message',
  id: number,
  message: string,
  senderType: string,        // 'human' | 'ai'
  senderName: string,
  artifactId?: string,
  streaming: boolean,
  regenerate: boolean,
  createdAt: string,          // ISO 8601
  llm?: number,              // LLM model ID
  files: File[],
  tags: Tag[],
  snippets: Snippet[],
  webSearchSources: WebSearchSource[],
  feedbackType?: string,
  feedbackText?: string,
  isEdited: boolean,
  isRegenerated: boolean,
  originalMessage?: string,
  cost?: string,
  inputTokens?: number,
  outputTokens?: number,
  energyWh?: number,
  carbonG?: number,
  waterMl?: number,
  generatedImage?: object,
  generatedTranscription?: object,
  learningProgressData?: object
}

message (type: ai_stream)

Streaming chunks during AI response generation.

{
  type: 'ai_stream',
  id: number,
  message: string,           // Accumulated text so far
  isComplete: boolean,
  senderName: string,
  senderType: string
}

message (type: artifact_init)

Artifact generation has started.

{
  type: 'artifact_init',
  artifactId: string,
  title: string,
  outline: string,
  estimatedSections: number
}

message (type: artifact_stream)

Streaming artifact content.

{
  type: 'artifact_stream',
  artifactId: string,
  chunk: string,
  section: number,
  progress: number           // 0.0 to 1.0
}

message (type: artifact_pause)

Artifact generation paused (user-initiated or section boundary).

{
  type: 'artifact_pause',
  artifactId: string,
  currentSection: number,
  sectionsRemaining: number
}

message (type: artifact_complete)

Artifact generation finished.

{
  type: 'artifact_complete',
  artifactId: string,
  totalWords: number,
  estimatedSections: number
}

message (type: voice_processing)

Voice message is being transcribed.

{ type: 'voice_processing', status: 'transcribing' }

message (type: voice_transcription)

Voice transcription result.

{
  type: 'voice_transcription',
  status: 'complete' | 'error',
  text?: string,
  error?: string
}

message (type: conversation_title)

Auto-generated conversation title.

{ type: 'conversation_title', title: string }

message (type: edit_message)

Confirmation that a message was edited.

{
  type: 'edit_message',
  id: number,
  message: string,
  isEdited: boolean
}

message (type: progress_stream / progress_complete / progress_error)

Learning progress assessment streaming (Socratic Books feature).

conversationId is the public Conversation.conversation_id used by subscribe_conversation and send_message (for example, OQ48N), never the database primary key. This also applies to latest_progress on subscription or reconnect, including an empty assessment. Clients use this ID to reject events from other conversations. Progress streams after the assistant response finishes; messageId remains the assessed message's database ID as a string.

// Streaming
{ type: 'progress_stream', conversationId: string, messageId: string, chunk: string }

// Complete
{ type: 'progress_complete', conversationId: string, messageId: string, inputTokens?: number, outputTokens?: number }

// Error
{ type: 'progress_error', message: string }

message (type: error)

Error during message processing.

{
  type: 'error',
  errorCode: string,
  errorMessage: string,
  details?: object
}

/workflow Namespace

Client → Server Events

subscribe_workflow

Subscribe to a workflow's execution state. Returns latest run and batch status.

FieldTypeRequiredDescription
workflowIdnumberYesWorkflow ID

Callback response:

{
  success: boolean,
  workflowId?: number,
  latestRun?: WorkflowRunState | null,
  latestBatchRun?: BatchRunState | null,
  error?: string
}

subscribe_workflow_run

Subscribe to a specific workflow run.

FieldTypeRequiredDescription
workflowRunIdnumberYesWorkflow run ID

Callback response: { success: boolean, error?: string, workflowRunId?: number }


unsubscribe_workflow_run

Leave a workflow run room.

FieldTypeRequiredDescription
workflowRunIdnumberYesWorkflow run ID

Callback response: { success: boolean, error?: string }


start_execution

Start or resume a workflow execution.

FieldTypeRequiredDescription
workflowRunIdnumberNoResume existing run
workflowIdnumberNoStart new run for workflow
userInputstringNoUser input for start node

Callback response: { success: boolean, error?: string, workflowRunId?: number }


execute_single_step

Execute a single node in manual mode.

FieldTypeRequiredDescription
workflowIdnumberYesWorkflow ID
stepNodeIdstringYesNode ID to execute
workflowRunIdnumberNoExisting run to continue

Callback response: { success: boolean, error?: string, workflowRunId?: number }


submit_validation

Submit a human validation decision at a routing node.

FieldTypeRequiredDescription
workflowRunIdnumberYesWorkflow run ID
nodeIdstringYesRouting node ID
selectedRoutestringYesChosen route name
continueExecutionbooleanNoContinue after validation (default: true)

Callback response: { success: boolean, error?: string }


start_batch_execution

Execute a workflow against multiple files.

FieldTypeRequiredDescription
workflowIdnumberYesWorkflow ID
fileIdsnumber[]YesFile IDs to process

Callback response: { success: boolean, error?: string, batchId?: number }


Server → Client Events

workflow_event (type: step_started)

A node has begun execution.

{
  type: 'step_started',
  nodeId: string,
  label?: string,
  nodeType: string,
  startedAt?: string,
  workflowRunId?: number
}

workflow_event (type: step_streaming)

Streaming LLM output from a step node.

{
  type: 'step_streaming',
  nodeId: string,
  chunk: string,
  accumulatedTokens?: number,
  workflowRunId?: number
}

workflow_event (type: step_completed)

A node has finished execution.

{
  type: 'step_completed',
  nodeId: string,
  response: string,
  status: 'completed' | 'failed' | 'skipped',
  tokens?: { input: number, output: number },
  metadata?: {
    snippets?: Snippet[],
    webSearchSources?: WebSearchSource[]
  },
  workflowRunId?: number
}

workflow_event (type: step_error)

A node encountered an error.

{
  type: 'step_error',
  error: string,
  nodeId?: string,
  errorType?: string,
  workflowRunId?: number
}

workflow_event (type: execution_complete)

The entire workflow run has finished.

{
  type: 'execution_complete',
  workflowRunId: number,
  status: 'completed' | 'failed' | 'pending_human_input',
  totalCost?: number,
  totalTokens?: { input: number, output: number },
  endedAt?: string
}

workflow_event (type: validation_required)

A routing node requires human input.

{
  type: 'validation_required',
  nodeId: string,
  routes: Array<{ name: string, description?: string }>,
  context?: { aiAnalysis?: string },
  aiRecommendation?: string,
  workflowRunId?: number
}

workflow_event (type: batch_started)

Batch execution has begun.

{
  type: 'batch_started',
  batchId: number,
  totalFiles: number,
  workflowId: number
}

workflow_event (type: batch_progress)

Progress update for a file in the batch.

{
  type: 'batch_progress',
  batchId: number,
  index: number,
  total: number,
  fileId: number,
  fileName: string,
  status: 'running' | 'completed' | 'failed',
  workflowRunId?: number
}

workflow_event (type: batch_complete)

Batch execution finished.

{
  type: 'batch_complete',
  batchId: number,
  completedCount: number,
  failedCount: number,
  totalFiles: number
}

workflow_status

Full snapshot of a workflow run state. Sent on subscribe and after significant state changes.

{
  type: 'workflow_status',
  id: number,
  status: string,
  startedAt?: string,
  endedAt?: string,
  workflowTitle?: string,
  workflowDescription?: string,
  isPartial?: boolean,
  nodeStates?: Record<string, NodeState>,
  pendingValidation?: {
    nodeId: string,
    routes: Array<{ name: string, description?: string }>,
    aiRecommendation?: string,
    context?: { aiAnalysis?: string }
  }
}

Shared Data Types

Snippet

{
  id: number,
  file?: { id: number, name: string },
  text: string,
  similarityScore: number,
  chunkIndex: number,
  vectorDbSource?: string
}

WebSearchSource

{
  id: number,
  url: string,
  title: string,
  citedText: string,
  pageAge?: string,
  provider: string
}

NodeState

{
  stepId?: number,
  startedAt?: string,
  nodeType: string,
  status: string,
  response?: string,
  error?: string,
  validationContext?: unknown,
  metadata?: unknown,
  snippets: Snippet[],
  webSearchSources: WebSearchSource[]
}

Implementation Notes

  • Event names are snake_case; payload keys are camelCase
  • Backend applies camelize() before all emissions
  • Frontend validates all /workflow events with Zod schemas in src/schemas/workflowSocket.ts
  • All client-to-server events use a callback pattern: socket.emit(event, data, callback)
  • Callbacks always return { success: boolean, error?: string } plus optional extra fields
  • Automatic re-subscription on reconnect via stored subscription sets in both middlewares

On this page