Docs

Documentation versions (currently viewingVaadin 25.1 (pre-release))

Conversation History & Session Persistence

Persist and restore conversation history, and reconnect the AIOrchestrator after session deserialization.

The orchestrator tracks conversation history internally. Use getHistory() to get a snapshot and withHistory() to restore it.

Persisting History

Use ResponseCompleteListener to persist conversation state after each successful exchange:

Source code
Java
var orchestrator = AIOrchestrator
        .builder(provider, systemPrompt)
        .withMessageList(messageList)
        .withInput(messageInput)
        .withResponseCompleteListener(event -> {
            var history = orchestrator.getHistory();
            saveToDatabase(sessionId, history);
        })
        .build();

The listener is not called when the response fails, times out, is empty, or when history is restored.

Important
UI Updates from ResponseCompleteListener
The listener runs on a background thread. It is safe to perform blocking I/O (such as database writes) directly. However, to update Vaadin UI components from this callback, wrap the update in ui.access().

Restoring History

Restore a previously saved conversation when creating a new orchestrator. The following example pre-populates the message list with a saved exchange:

Source code
AIOrchestratorHistory.java

This replays messages into the LLM provider’s memory, populates the Message List UI, and rebuilds internal mappings for attachment click handling.

Note
getHistory() returns a point-in-time snapshot. If called while a streaming response is in progress, the snapshot may include the user message without its corresponding assistant response. Use ResponseCompleteListener to capture history at the right time.

Data Model

Conversation history is represented as a list of ChatMessage records with four fields:

  • role() — USER or ASSISTANT

  • content() — the text content

  • messageId() — UUID assigned to user messages; null for assistant messages. Used as the correlation key for attachments.

  • time() — timestamp; may be null

File attachments are represented as AIAttachment records with name(), mimeType(), and data() (raw bytes). Attachments are not stored in ChatMessage — they are correlated separately via the message ID.

Session Persistence

AIOrchestrator is serializable. Conversation history, UI component bindings, listener registrations, and display names are preserved across serialization. However, the LLM provider and tool objects are transient — they are not serialized and must be restored after deserialization.

Reconnecting After Deserialization

After the session is restored, call reconnect(LLMProvider) to supply a new provider and optionally restore tools and file attachments. The apply() call replays the existing conversation history onto the new provider so that it has full context for subsequent prompts. The UI is not modified — the message list, input, and file receiver components retain their state automatically.

Source code
Java
// After session restore, reconnect the orchestrator
LLMProvider provider = getNewLLMProvider();
Map<String, List<AIAttachment>> savedAttachments =
        getSavedAttachments();

orchestrator.reconnect(provider)
        .withTools(new WeatherTools())      // optional
        .withAttachments(savedAttachments)  // optional
        .apply();

If prompt() is called before reconnecting, it throws an IllegalStateException.

Note
LLMProvider Implementations
LLMProvider implementations are not serializable. Always create a new provider instance after session restore and pass it to reconnect().