Message Handling

Understanding how messages flow through the Intercom component, from sending to receiving streaming responses.


Message Flow Overview

The Intercom component handles two types of message operations:

  1. Sending Messages - User sends messages to deva

  2. Receiving Messages - Deva responds with streaming messages


Sending Messages

User Input

Messages are sent through the input field at the bottom of the chat interface.

Flow:

  1. User types message in input field

  2. User presses Enter or clicks send button

  3. Message is sent to API

  4. Message appears immediately in chat (optimistic update)

  5. Server confirms and returns message ID

  6. Message streaming begins for deva response

Message Structure

User messages contain:

  • text: Message content

  • thread_id: Conversation thread identifier

  • persona_id: User's persona ID

  • created_at: Timestamp


Receiving Messages

Real-Time Streaming

Deva responses stream in real-time using Server-Sent Events (SSE):

Stream Phases:

  1. Incoming Indicator

    • Shows typing indicator (three bouncing dots)

    • Indicates deva is preparing response

  2. Content Streaming

    • Text streams word-by-word

    • Updates in real-time as content arrives

    • Shows partial message with accumulated content

  3. Stream Complete

    • Final message object received

    • Streaming stops

    • Complete message displays in chat

Stream Events

The SDK uses fetchEventSource to handle SSE streams:

Event Types:

  • content - Partial content chunks

  • response_message - Complete message object

  • completion - Stream completed successfully


Message States

Optimistic Updates

When user sends a message:

// Message appears immediately
mutate(userMessage);

// Then confirmed by server
// If error, message is rolled back

Benefits:

  • Instant feedback

  • Better user experience

  • Handles network delays gracefully

Loading States

User Message:

  • Shown immediately (optimistic)

  • Loading indicator if network slow

Deva Response:

  1. Initial: Typing indicator (three dots)

  2. Streaming: Partial text with blinking cursor

  3. Complete: Full message displayed


Message History

Pagination

Messages load in batches:

  • Initial load: 10 most recent messages

  • Load more: Scroll up to load older messages

  • Batch size: 10 messages per page

Implementation:

const {
  messages,
  hasNext,
  fetchNext
} = useDevaMessages({ threadId });

Scroll Behavior

Auto-scroll:

  • Scrolls to bottom when new message arrives

  • Scrolls to bottom when user sends message

  • Maintains position when loading older messages

Manual scroll:

  • User can scroll up to view history

  • Triggers pagination when reaching top

  • Preserves scroll position during pagination


Streaming Implementation

How Streaming Works

// 1. User sends message
const message = await sendMessage(text);

// 2. SDK starts listening for deva response stream
const streamUrl = `${url}/api/sdk/chat/${threadId}/messages/${messageId}/query/stream`;

// 3. Stream opens
fetchEventSource(streamUrl, {
  onopen: () => {
    // Connection established
  },

  onmessage: (event) => {
    if (event.type === "content") {
      // Accumulate content chunks
      accumulatedContent += event.data;
      updateMessage(accumulatedContent);
    }

    if (event.type === "response_message") {
      // Final message received
      setCompleteMessage(event.data);
    }
  },

  onerror: (error) => {
    // Handle stream errors
  },

  onclose: () => {
    // Stream completed
  }
});

Stream States

Active Stream:

  • Shows typing indicator

  • Updates text in real-time

  • Prevents new messages until complete

Complete Stream:

  • Shows final message

  • Enables new message sending

  • Adds message to history

Error Stream:

  • Shows error indicator

  • Allows retry

  • Maintains previous messages

Learn more about the Streaming Implementation.


Error Handling

Network Errors

When network fails:

  • Shows error message

  • Maintains optimistic message

  • Allows retry

Stream Errors

When stream fails:

  • Shows "Problem" error indicator

  • Displays error message

  • Stream is aborted

  • Chat remains functional

Message Send Errors

When sending fails:

  • Message not added to history

  • Error displayed

  • User can retry

Learn more about the Error Handling.


Message Types

User Messages

Properties:

  • text: Message content

  • persona_id: User's persona

  • author_type: "USER"

  • created_at: Timestamp

Display:

  • Right-aligned

  • User avatar

  • User's display name

Deva Messages

Properties:

  • text: Response content (streamed)

  • persona_id: Deva's persona

  • author_type: "BOT"

  • created_at: Timestamp

Display:

  • Left-aligned

  • Deva avatar

  • Deva's display name

Learn more about the Message Types.


Thread Management

Thread Creation

Threads are created automatically:

// First message to a deva creates thread
const thread = await createDMThread(devaUsername);

// Subsequent messages use existing thread

Thread Persistence

  • Threads persist across sessions

  • Message history maintained

  • Thread ID stored in component state

Learn more about the Thread Types.


Best Practices

Message Sending:

  • Trim whitespace before sending

  • Validate non-empty messages

  • Show loading state during send

  • Handle errors gracefully

Receiving Messages:

  • Auto-scroll to new messages

  • Maintain scroll position during pagination

  • Show clear loading indicators

  • Handle stream interruptions

Performance:

  • Use optimistic updates for instant feedback

  • Paginate message history

  • Abort streams when component unmounts

  • Clean up event listeners


Advanced Features

Infinite Scroll

Messages load automatically when scrolling up:

Implementation:

  1. Intersection Observer watches top of message area

  2. When user scrolls near top, triggers fetchNext()

  3. Loads 10 more messages

  4. Maintains scroll position

  5. Repeats until no more messages

Stream Interruption

Streams can be interrupted:

  • User closes chat (stream aborted)

  • Component unmounts (cleanup)

  • Network disconnects (error handling)

  • New message sent (current stream completes first)


During streaming, partial message:

{
  id: string;
  text: string; // Accumulated content so far
  // Other fields populated when complete
}

Core Concepts:

Last updated