The CollectingDispatcher is the primary object used within custom actions to communicate with the user. It supports two modes of operation:
- Unary API: Use
utter_message() to send complete messages (text, images, buttons, etc.). These are accumulated and returned as a single payload at the end of the action. - Streaming API: Use
stream_start(), stream_chunk(), and stream_end() to emit responses incrementally (e.g., for LLM token streaming).
Crucially, action authors do not need to worry about the transport layer. If the transport supports streaming, chunks are sent immediately. If not, stream_end() automatically replays all accumulated chunks as individual utter_message() calls, ensuring your action works correctly on all platforms.
async def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Domain,
)
# Unary: Send a complete message
dispatcher.utter_message(text="Hello!", buttons=[{"button": {"text": "Yes", "payload": "confirm"}}])
# Streaming: Send incremental chunks
await dispatcher.stream_start()
await dispatcher.stream_chunk(text="This ")
await dispatcher.stream_chunk(text="is ")
await dispatcher.stream_chunk(text="streaming.")
await dispatcher.stream_end()
return []