Managing Dialogue State in Dyalog: A Practical Coffee‑Order Bot Example
Learn how Dyalog’s dialogue state tracking lets you build a multi‑turn coffee‑order bot that remembers slots across user turns, with a concrete schema, example flow, and notes on overhead.
25 Apr 2026, 07:47 UTC

Problem: Keeping track of a multi‑turn conversation
When a user wants to order a coffee, they might first say “I’d like a latte”, then later specify the size, and finally confirm the pickup time. If the bot forgets earlier details after each turn, the user has to repeat themselves, which feels brittle and frustrating.
Thesis
Dyalog’s built‑in dialogue state tracking lets you store collected slots across turns, so you only ask for missing information once. By defining intents, slots, and a simple fallback, you can build a reliable ordering flow without writing custom state‑management code.
Defining the intent and slots
First, declare a schema that maps the user’s goal to an intent and lists the required pieces of information (slots). In Dyalog this is done with a JSON‑like file.
{
"intents": {
"OrderCoffee": {
"description": "User wants to purchase a coffee drink",
"slots": [
{ "name": "drinkType", "type": "string", "required": true },
{ "name": "size", "type": "enum", "values": ["small","medium","large"], "required": true },
{ "name": "pickupTime", "type": "time", "required": false }
],
"handler": "src/handlers/orderCoffee.js"
}
},
"fallback": {
"handler": "src/handlers/fallback.js"
}
}
The schema tells Dyalog that to fulfill OrderCoffee it must collect drinkType, size, and optionally pickupTime. Until all required slots have values, the framework will keep the conversation open and prompt for the missing ones.
How state is managed across turns
Each time the user sends a message, Dyalog runs the NLU model, updates the internal state object with any newly recognized slots, and then checks the intent’s slot completion status. If any required slot is still empty, the framework selects the next appropriate prompt (you can define prompts per slot in a separate file). When all required slots are present, it invokes the handler you specified.
You can inspect the current state by enabling debug logging:
# Run the bot with verbose logging
node bot.js --log-level debug
The log will show lines like:
[debug] State after turn 1: { drinkType: "latte" }
[debug] State after turn 2: { drinkType: "latte", size: "medium" }
[debug] All required slots filled → invoking handler
This makes it easy to verify that slots are persisting as expected.
Worked example: ordering a latte
- User: “I’d like a latte”.
- NLU recognizes
drinkType=latte. State now holds only that slot. - Dyalog sees
sizemissing, prompts: “What size would you like?” - User: “Medium”.
- NLU adds
size=medium. State now has both required slots. - All required slots present → Dyalog calls
src/handlers/orderCoffee.jswith the full payload. - Handler returns a confirmation message, which Dyalog sends back to the user.
If the user later adds “Please have it ready by 10:30”, the optional pickupTime slot is filled, but the handler would have already been called; you can design the handler to accept optional slots and incorporate them into the response.
Trade‑off and limitation
Storing the full dialogue state for each conversation adds memory overhead. In a bot with dozens of intents and many slots per intent, the state object can grow large, especially if you keep history for analytics. To mitigate this, you can:
- Turn off state persistence for intents that do not need slot collection (set
"persistState": falsein the intent definition). - Periodically snapshot and archive state to a database, clearing the in‑memory object after a timeout.
You can check the memory impact by running the bot under a load simulator and observing the process RSS (resident set size) before and after enabling state persistence for a high‑slot intent.
Actionable closing
Start with a small schema like the coffee‑order example, enable debug logs, and verify that slots accumulate correctly across turns. Once the basic flow works, add more intents and consider the state‑persistence tweaks above to keep the bot scalable as your conversation tree expands.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.