Session Lifecycle
Session ID
Every session has a unique session_id (UUID v4) automatically generated and attached to the metadata of every event in that session. No configuration is required.
When a new session_id is generated
| Trigger | Description |
|---|---|
| Brand new conversation | First event on a tracker |
action_session_start / SessionStarted | A new session starts |
ConversationResumed | Explicit resumption after inactivity |
UserUttered on an inactive tracker | User reactivates an inactive conversation |
session_id in event metadata
All events within the same session share the same session_id. A new session carries a new UUID.
{
"event": "user",
"text": "Hello",
"metadata": {
"session_id": "4b3c1e2a-91f0-4d8e-b123-abc123def456"
}
}
current_session_id on the tracker
The tracker also exposes a current_session_id field, so you can read the active session ID at any point during the conversation:
{
"sender_id": "conversation_12345",
"current_session_id": "4b3c1e2a-91f0-4d8e-b123-abc123def456",
"events": [...]
}
Conversation Lifecycle Events
ConversationInactive
ConversationInactive marks a conversation as inactive but resumable. It is emitted automatically by the session timer when the inactivity timeout elapses.
Tracker effects:
inactive = trueis set on the tracker.- The conversation continues to accept new events.
- The inactive state is cleared when a
UserUtteredorConversationResumedevent is received.
SessionEnded
SessionEnded marks a conversation as permanently terminated. No further events can be appended after this point.
Tracker effects:
terminated = trueis set on the tracker.- All subsequent attempts to append events are rejected.
- The session timer is cancelled immediately.
How to trigger SessionEnded
Via a custom action:
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.events import SessionEnded
class ActionEndSession(Action):
def name(self):
return "action_end_session"
async def run(self, dispatcher, tracker: Tracker, domain):
return [SessionEnded()]
When a custom action returns SessionEnded, Rasa stops the prediction loop and flow executor immediately. No further actions are predicted or executed.
Via the REST API:
curl -X POST http://localhost:5005/conversations/{conversation_id}/tracker/events \
-H "Content-Type: application/json" \
-d '{"event": "session_ended"}'
When SessionEnded is posted via the API, the session timer is cancelled unconditionally, regardless of whether execute_side_effects is set.
If an A2A sub agent task is running in the background, it is also cancelled.
Likewise, posting a ConversationInactive event through the same endpoint cancels in-flight background A2A processing for that conversation.
Comparison
| Event | Tracker state | Resumable | Triggered by | Further events |
|---|---|---|---|---|
ConversationInactive | inactive = true | Yes | Inactivity timer | Accepted |
SessionEnded | terminated = true | No | Custom action or REST API | Rejected. |