Persisting Conversation State Before Sending a WhatsApp Reply
Suppose a conversation asks for a missing detail. The reply is sent successfully, and the user answers immediately. If the workflow has not yet stored which detail it requested, the next turn arrives against the previous state.
The generated sentence can be correct while the conversation is already broken.
In the local workflow exports, the qualification path addresses this with a synchronous critical state write before the outgoing reply. Other bookkeeping can happen later, but the state needed to interpret the next message cannot.
Define what must be durable first
The critical boundary includes the current control state and the expected next input. It is narrower than every piece of data produced by the turn.
A simplified sequence is:
interpret message
prepare next state
persist critical state and await completion
check duplicate or conflict result
send reply if still allowed
perform remaining bookkeeping
This ordering prevents a reply from advertising a conversation state that exists only in workflow memory.
It also avoids turning every nonessential update into a reason to delay a response. Historical activity references and other secondary writes have different urgency from the next expected answer.
The subworkflow must actually finish
Calling a persistence workflow is not the same as waiting for it. The adapter explicitly waits for the critical persistence subworkflow and checks for its successful terminal result.
A missing completion flag is treated as failure. That is useful because an execution node can return a structurally valid payload that does not prove the intended write completed.
The boundary is semantic: did the state writer finish the required operation? A generic success-shaped object is insufficient.
Duplicate and conflict results can suppress a reply
The persistence result can report a duplicate inbound message or a stale state conflict. In those cases the adapter clears the outgoing reply and disables the send path.
That prevents a delayed workflow execution from answering after another execution has already advanced the conversation.
The appointment branch is handled separately. The qualification pre-persist condition excludes an active appointment flow, so a qualification rule does not accidentally become a competing authority for an appointment turn.
This is not an atomic messaging transaction
Persisting first introduces a different failure case: the state can advance and the external send can fail. The database and messaging provider do not share one transaction.
That means retries need message identity and delivery context. Blindly rerunning the complete turn can advance the state again or produce another reply. A durable outbound queue is one possible next step, but this pre-send boundary alone should not be described as exactly-once delivery.
The concrete improvement is narrower and valuable: a successful outgoing question no longer depends on an asynchronous control-state write winning a race against the user's next message.