The parser was not the real bug

One of the nastier failure modes in a conversational workflow is not a wrong answer. It is two locally sensible answers to the same message.

An appointment branch can correctly recognise a requested date and produce alternatives. At the same time, qualification logic can still be waiting for an earlier field and classify that exact message as an unclear answer. Both branches have enough local context to believe they should respond.

The result is not an AI problem. It is an ownership problem.

Central arbitration

I treat branch selection as an explicit step before qualification and appointment processing. Appointment context gets priority when the conversation already has proposed slots, a pending appointment action, a selected slot, or an active cancellation or rescheduling flow.

incoming message
โ†’ decide authoritative branch
โ†’ execute that branch
โ†’ persist its output

When the appointment branch wins, qualification capture must not run for that turn. Improving a language model would not fix a system that lets two independent branches act after routing.

Output ownership matters too

Choosing a branch is only half the protection. The winning branch needs to own final fields such as reply text, pending action, proposed slots, selected slot, and appointment write intent. A later step must not quietly overwrite them with a qualification result.

What I learned

Distributed branch logic is dangerous because each branch can be individually correct while the full execution is wrong. Every message needs one explicit owner.

The related persistence rule is covered in designing consistent conversation state across workflows.

What should happen next

I want a formal transition table: which states accept which intents, which workflow owns each transition, and which fields that transition is allowed to change.