Cosmo Realtime SDK
Production

Session limits & resume

Wall-clock caps, the ending-soon warning, and continuing a conversation in a new session.

Sessions don't run forever. A wall-clock cap protects you from runaway costs (a forgotten tab, a voicemail system that never hangs up) and lets the platform bound resources. The SDK tells you the effective cap, warns before it fires, and gives you a resume path when a conversation legitimately needs more time.

Setting a cap

The wire protocol accepts a requested cap per run (max_session_seconds, 60–14400). The server enforces the minimum of your request and its own limits — you can shorten a session, never extend one. Swift exposes the request directly:

var config = SessionConfig()
config.maxSessionSeconds = 900   // 15 minutes

TypeScript and Python sessions currently run under the server's default cap. In every SDK, the effective value is reported on the ready event — read it from there rather than assuming a request was granted:

session.on('ready', ({ maxSessionSeconds }) => {
  scheduleWrapUpTimer(maxSessionSeconds);
});
case RealtimeReady():
    print(f"cap: {event.max_session_seconds}s")

The shutdown sequence

As the deadline approaches, the server pushes warnings, then ends the session:

  1. session-ending-soon — carries seconds_remaining and a reason slug. This is your window to have the agent wrap up naturally, save state, or offer continuation.
  2. session-ended — the server's deliberate goodbye, with reason (e.g. max_session_duration).
  3. The stream finishes with the terminal session-ended item, as on every exit path.

A good voice UX treats session-ending-soon as a conversational event, not just a log line — inject a wrap-up cue via send_text or surface a "continue?" affordance in the UI.

Resuming a conversation

resume_session_id starts a new session that continues a prior one's conversation:

first = await agent.start()
# … session ends (cap, network, user closed the app) …

again = await agent.start(resume_session_id=first.session_id)
# the agent remembers the conversation

Under the hood the server does whichever is possible: native resumption when the upstream model session is still warm, or seeded continuation (replaying the transcript into a fresh model session) when it isn't. Either way the agent picks up with context; either way it does not re-speak its greeting — greetings belong to first contact.

resume_session_id is an experimental session param: it works today, but its shape may change without a protocol-version bump. Pin your SDK version if you build a core flow on it.

Resume is per-conversation continuity, not durable memory: it stitches one user's interrupted conversation back together. Long-term memory across days and sessions belongs in your own store, injected via instructions, a SessionStart hook, or session state capture.

Wall-clock caps interact with the platform's metering: concurrent-session and usage limits are account-level and documented in Limits. Transport-level drops within a session's lifetime are a different topic — see Reconnects.

On this page