The SDK supports three strategies for managing conversation history: full manual control via result.to_input_list(), SDK-managed persistence through Session implementations, or server-side state via OpenAI response IDs—allowing callers to choose based on their persistence needs. Session is a structural Protocol, not a class hierarchy; third-party implementations only need the session_id attribute and get_items(), pop_item(), add_items(), clear_session() methods, and may optionally implement run_compaction() for responses compaction support.
For multi-turn conversations, callers choose between result.to_input_list() (full manual history control, provider-agnostic), session=... (SDK-managed persistence), or previous_response_id/conversation_id (OpenAI server-side state).[1]
Session in src/agents/memory/session.py is a @runtime_checkable Protocol, meaning third-party implementations only need to satisfy the structural interface — they are NOT required to inherit from any base class.[2] Every Session implementation must expose a session_id: str attribute and an optional session_settings: SessionSettings | None (defaults to None).[2] Session.get_items(limit) retrieves conversation history; when limit is specified it returns the latest N items in chronological order; when None it returns all items.[2] Session.pop_item() removes and returns the most recent item from the session, or None if the session is empty.[2] SessionABC in src/agents/memory/session.py is an abstract base class intended for internal use and as a base for concrete implementations; third-party libraries should implement the Session Protocol instead.[2]
OpenAIResponsesCompactionAwareSession is a @runtime_checkable Protocol that extends Session with a run_compaction(args) method for sessions that support responses compaction.[2] OpenAIResponsesCompactionArgs.compaction_mode has three values: "auto" (use input when the last response was not stored), "previous_response_id" (use server-managed response history), and "input" (send locally stored session items as input).[2] When OpenAIResponsesCompactionArgs.store is False, compaction should avoid "previous_response_id" mode unless explicitly requested.[2] is_openai_responses_compaction_aware_session() in src/agents/memory/session.py checks for compaction support by looking for a callable run_compaction attribute on the session; it returns False for None or any session where attribute access raises.[2]
Custom Session implementations can opt into receiving the RunContextWrapper by adding a wrapper keyword parameter to all four history methods (get_items, add_items, pop_item, clear_session); the public Session Protocol does not include wrapper so existing structural implementations remain type-compatible.[2] _session_accepts_wrapper() in src/agents/memory/session.py requires ALL four history methods to accept wrapper — if any one method lacks it, wrapper is not passed to any method.[2] _get_session_wrapper() in src/agents/memory/session.py returns None (suppressing context propagation) whenever wrapper is None OR the session does not have a complete context-aware contract (all four methods accept wrapper).[2] _call_session_method() in src/agents/memory/session.py transparently handles both sync and async session method implementations — it awaits the result only when inspect.isawaitable returns True.[2]
Sources