Skip to main content

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

TriggerDescription
Brand new conversationFirst event on a tracker
action_session_start / SessionStartedA new session starts
ConversationResumedExplicit resumption after inactivity
UserUttered on an inactive trackerUser 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 = true is set on the tracker.
  • The conversation continues to accept new events.
  • The inactive state is cleared when a UserUttered or ConversationResumed event is received.

SessionEnded

SessionEnded marks a conversation as permanently terminated. No further events can be appended after this point.

Tracker effects:

  • terminated = true is 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

EventTracker stateResumableTriggered byFurther events
ConversationInactiveinactive = trueYesInactivity timerAccepted
SessionEndedterminated = trueNoCustom action or REST APIRejected.