> ## Documentation Index
> Fetch the complete documentation index at: https://rasa.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Timer

> Configure a session timer to automatically mark conversations as inactive after a period of inactivity.

Rasa maintains one active timer per conversation. When the timer fires, a `ConversationInactive` event is emitted automatically.

For each active conversation:

1. A timer is scheduled when a session starts.
2. The timer resets every time a user message is received.
3. When the timer fires, `ConversationInactive` is emitted.
4. If `SessionEnded` is received (via custom action or REST API), the timer is immediately cancelled.

### Configuring the timeout

Set `session_expiration_time` in `session_config` in `domain.yml` to control how long user inactivity is allowed before the timer fires:

```yaml theme={null}
session_config:
  session_expiration_time: 60              # minutes; 0 disables session expiry
  carry_over_slots_to_new_session: true
  start_session_after_expiry: true         # new in 3.16, true by default for backward compatibility
```

### `start_session_after_expiry`

In both cases (true or false), when the timer fires, the `ConversationInactive` event is emitted and the tracker is marked as inactive.
The difference is what happens when the next user message arrives.

**`true` (default — existing behaviour):**

When the next user message arrives after expiry:

1. A session boundary is created (`SessionStarted` is emitted, `action_session_start` runs).
2. A new `session_id` is generated as part of the session boundary and stamped on all subsequent events.

**`false` (new in 3.16):**

When the next user message arrives after expiry:

1. No session boundary is created (`SessionStarted` is not emitted, and `action_session_start` does not run).
2. A new `session_id` is still generated on the `UserUttered` event and stamped on all subsequent events.

<Note>
  `carry_over_slots_to_new_session` has no effect when `start_session_after_expiry` is `false`.
  No session boundary is created, so slots are preserved as-is.
  Rasa will log a warning if both are set to `false` together.
</Note>

If you expect your users to return to a conversation after a period of inactivity, set `start_session_after_expiry` to `false` to retain the conversation uninterrupted and avoid unnecessary session boundaries.

<Warning>
  **Required for A2A sub-agent mode**

  When `a2a_server` is configured in `endpoints.yml`, `start_session_after_expiry` **must be `false`**.

  Resumed orchestrator `contextId` values reuse the same Rasa `sender_id`. If `start_session_after_expiry` is `true`, Rasa runs `action_session_start` after inactivity and can silently reset slot state when the orchestrator resumes the same context.

  Rasa validates this at model load and refuses to start with error code `validation.a2a_server.incompatible_session_config`.

  `ConversationInactive` does not release an `input_required` A2A context — the next message on the same `contextId` continues the flow when this setting is `false`.

  See [A2A Server](/docs/reference/integrations/a2a-server#session-configuration) and [Session configuration](/docs/reference/config/domain#session-configuration).
</Warning>

### Timer store

Because Rasa maintains one active timer per conversation, those timers need somewhere to live — especially across restarts and in multi-pod deployments.
The `timer_store` in `endpoints.yml` controls where they are stored. Read more about timer store options in the [Timer Stores documentation](/docs/reference/integrations/timer-stores).


## Related topics

- [Timer Stores](/docs/reference/integrations/timer-stores.md)
- [Session Lifecycle](/docs/reference/config/session-management/session-lifecycle.md)
- [Session Management Overview](/docs/reference/config/session-management/overview.md)
- [Domain](/docs/reference/config/domain.md)
- [Rasa Pro Change Log](/docs/reference/changelogs/rasa-pro-changelog.md)
