Best practices for message persistence with DurableAgent? #688
Unanswered
brenbitY2K
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm building a chat application using
DurableAgentwith human-in-the-loop interactions viadefineHook. The workflow can pause for extended periods (days) waiting for user input, which might come from the chat UI or from external triggers like email webhooks.I want to understand the recommended patterns for:
My Current Understanding
This could be way off, but this is what I've gathered from digging through the codebase:
While we're suspended due to the hook, the messages still exist "in memory" for that workflow run, so no immediate need to save to the DB yet. When the workflow fully completes, that's when we need to worry about persisting the messages b/c the workflow is over and the next request has no memory of the prior messages (unless explicitly sent over obviously).
Message format challenge:
DurableAgent.stream()returnsModelMessage[], but we store messages asUIMessage[]. ThecreateUIMessageStreamwrapper on the client/server reconstructsUIMessage[]from stream chunks in itsonFinishcallback.Since
ModelMessagecontains less information thanUIMessage, the reliable place to get the fullUIMessageformat is from the stream consumer (client or proxy), not from the workflow itself. This is how most people use the AI SDK. We can't really do this in the workflow unless we set up some proxy server that reads the stream and runscreateUIMessageStreamjust to be able to save duringonFinishwhich kind of defeats the ergonomics of the Workflow SDK IMO.Proposed Architecture
Based on the
flight-booking-apppattern, I'm considering:WorkflowChatTransportwithonChatEndcallbackonChatEndfires → ?Questions
1. Is client-side persistence the recommended pattern?
The
flight-booking-appexample uses localStorage. For production apps needing durable storage (Postgres), is having the client call a save endpoint inonChatEndthe intended approach?2. Stream chunk retention after workflow completion
If a workflow completes while no client is connected, and the user opens the app later:
getRun(runId).getReadable({ startIndex: 0 })still return all chunks?3. Email/webhook resume with no client
Consider this scenario:
When the user eventually opens the client, will reconnection work and
onChatEndfire? Or do we need a fallback persistence mechanism in the workflow itself for this case?Summary
I want to confirm that the recommended architecture is:
onChatEnd)Is this correct, or are there patterns we're missing for production use cases? If we just saved messages as
ModelMessagethen there's really no issue here, but saving asUIMessageis a must.Beta Was this translation helpful? Give feedback.
All reactions