Summary
Assistant responses are currently persisted by the frontend: the browser receives the assistant_message event over SignalR and POSTs it to the chat API. If the user leaves the page while the agent is working, the workflow completes server-side but the answer is never persisted — the user returns to an empty thread and assumes the agent failed.
Move persistence of assistant messages to the server so a completed workflow always produces a stored message, regardless of whether a browser tab is listening.
Context
Observed in practice (trace b8e945bf47898d9392df41bffece9f29): the user navigated away mid-run, the workflow completed successfully in ~26s with a full answer, success=true — but nothing appeared in the thread, because nobody was there to persist it.
Current flow:
- Agents service emits
assistant_message → Designer backend (AltinityWebSocketService) forwards it to the SignalR group → frontend useAltinityWorkflow.handleAssistantMessage → createMessage POST to the chat API.
- Every step after SignalR forwarding requires a live, connected tab. The agents service keeps its own conversation history for model context, but the Designer chat database — which the UI renders from — is only written by the client.
This also means a network blip at the wrong moment, a laptop lid close, or a tab crash silently discards completed work.
Goal
Ensure the assistant's final message (including filesChanged, sources, and trace ID) is persisted to the chat store server-side when the workflow completes, with the frontend reduced to rendering — so the user can leave, come back, and find the answer waiting.
In scope
- Persist
assistant_message events server-side — natural candidate: the Designer backend at the point it already receives every agent event (AltinityWebSocketService), which knows the developer/thread from session registration
- Persist the message with full metadata: content,
filesChanged, sources, trace ID
- Remove (or dedupe against) the frontend's
createMessage call for assistant messages so the transition doesn't double-persist
- Verify the returning user sees the persisted answer on thread reload
- Decide handling for rejection/error messages the frontend currently synthesizes client-side (
formatRejectionMessage, workflow-error fallback)
Out of scope
- Changes to the agent workflow, events, or the agents service's own conversation history
- Live-reconnect/resume of an in-progress activity trail (the user returning mid-run sees the trail from scratch; separate concern)
- Persistence of user messages (already persisted before the workflow starts)
- Chat storage schema changes beyond what the message metadata requires
Acceptance criteria
Relationship to other work
This contributes to beta readiness: silent loss of completed work is a trust-breaking failure mode for real users. It was surfaced by the evaluation work on the unified-agent branch (the "lost" run was fully visible in Langfuse, proving the backend succeeded while the product dropped the result).
Summary
Assistant responses are currently persisted by the frontend: the browser receives the
assistant_messageevent over SignalR and POSTs it to the chat API. If the user leaves the page while the agent is working, the workflow completes server-side but the answer is never persisted — the user returns to an empty thread and assumes the agent failed.Move persistence of assistant messages to the server so a completed workflow always produces a stored message, regardless of whether a browser tab is listening.
Context
Observed in practice (trace
b8e945bf47898d9392df41bffece9f29): the user navigated away mid-run, the workflow completed successfully in ~26s with a full answer,success=true— but nothing appeared in the thread, because nobody was there to persist it.Current flow:
assistant_message→ Designer backend (AltinityWebSocketService) forwards it to the SignalR group → frontenduseAltinityWorkflow.handleAssistantMessage→createMessagePOST to the chat API.This also means a network blip at the wrong moment, a laptop lid close, or a tab crash silently discards completed work.
Goal
Ensure the assistant's final message (including
filesChanged,sources, and trace ID) is persisted to the chat store server-side when the workflow completes, with the frontend reduced to rendering — so the user can leave, come back, and find the answer waiting.In scope
assistant_messageevents server-side — natural candidate: the Designer backend at the point it already receives every agent event (AltinityWebSocketService), which knows the developer/thread from session registrationfilesChanged,sources, trace IDcreateMessagecall for assistant messages so the transition doesn't double-persistformatRejectionMessage, workflow-error fallback)Out of scope
Acceptance criteria
filesChanged,sources, and trace ID (feedback buttons still work)Relationship to other work
This contributes to beta readiness: silent loss of completed work is a trust-breaking failure mode for real users. It was surfaced by the evaluation work on the unified-agent branch (the "lost" run was fully visible in Langfuse, proving the backend succeeded while the product dropped the result).