Sessions
The Agents SDK provides built-in session memory to automatically maintain conversation history across multiple agent runs, eliminating the need to manually handle.to_input_list() between turns.
Sessions stores conversation history for a specific session, allowing agents to maintain context without requiring explicit manual memory management. This is particularly useful for building chat applications or multi-turn conversations where you want the agent to remember previous interactions.
Quick start
fromagentsimportAgent,Runner,SQLiteSession# Create agentagent=Agent(name="Assistant",instructions="Reply very concisely.",)# Create a session instance with a session IDsession=SQLiteSession("conversation_123")# First turnresult=awaitRunner.run(agent,"What city is the Golden Gate Bridge in?",session=session)print(result.final_output)# "San Francisco"# Second turn - agent automatically remembers previous contextresult=awaitRunner.run(agent,"What state is it in?",session=session)print(result.final_output)# "California"# Also works with synchronous runnerresult=Runner.run_sync(agent,"What's the population?",session=session)print(result.final_output)# "Approximately 39 million"How it works
When session memory is enabled:
- Before each run: The runner automatically retrieves the conversation history for the session and prepends it to the input items.
- After each run: All new items generated during the run (user input, assistant responses, tool calls, etc.) are automatically stored in the session.
- Context preservation: Each subsequent run with the same session includes the full conversation history, allowing the agent to maintain context.
This eliminates the need to manually call.to_input_list() and manage conversation state between runs.
Memory operations
Basic operations
Sessions supports several operations for managing conversation history:
fromagentsimportSQLiteSessionsession=SQLiteSession("user_123","conversations.db")# Get all items in a sessionitems=awaitsession.get_items()# Add new items to a sessionnew_items=[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi there!"}]awaitsession.add_items(new_items)# Remove and return the most recent itemlast_item=awaitsession.pop_item()print(last_item)# {"role": "assistant", "content": "Hi there!"}# Clear all items from a sessionawaitsession.clear_session()Using pop_item for corrections
Thepop_item method is particularly useful when you want to undo or modify the last item in a conversation:
fromagentsimportAgent,Runner,SQLiteSessionagent=Agent(name="Assistant")session=SQLiteSession("correction_example")# Initial conversationresult=awaitRunner.run(agent,"What's 2 + 2?",session=session)print(f"Agent:{result.final_output}")# User wants to correct their questionassistant_item=awaitsession.pop_item()# Remove agent's responseuser_item=awaitsession.pop_item()# Remove user's question# Ask a corrected questionresult=awaitRunner.run(agent,"What's 2 + 3?",session=session)print(f"Agent:{result.final_output}")Session types
The SDK provides several session implementations for different use cases:
OpenAI Conversations API sessions
UseOpenAI's Conversations API throughOpenAIConversationsSession.
fromagentsimportAgent,Runner,OpenAIConversationsSession# Create agentagent=Agent(name="Assistant",instructions="Reply very concisely.",)# Create a new conversationsession=OpenAIConversationsSession()# Optionally resume a previous conversation by passing a conversation ID# session = OpenAIConversationsSession(conversation_id="conv_123")# Start conversationresult=awaitRunner.run(agent,"What city is the Golden Gate Bridge in?",session=session)print(result.final_output)# "San Francisco"# Continue the conversationresult=awaitRunner.run(agent,"What state is it in?",session=session)print(result.final_output)# "California"SQLite sessions
The default, lightweight session implementation using SQLite:
fromagentsimportSQLiteSession# In-memory database (lost when process ends)session=SQLiteSession("user_123")# Persistent file-based databasesession=SQLiteSession("user_123","conversations.db")# Use the sessionresult=awaitRunner.run(agent,"Hello",session=session)SQLAlchemy sessions
Production-ready sessions using any SQLAlchemy-supported database:
fromagents.extensions.memoryimportSQLAlchemySession# Using database URLsession=SQLAlchemySession.from_url("user_123",url="postgresql+asyncpg://user:pass@localhost/db",create_tables=True)# Using existing enginefromsqlalchemy.ext.asyncioimportcreate_async_engineengine=create_async_engine("postgresql+asyncpg://user:pass@localhost/db")session=SQLAlchemySession("user_123",engine=engine,create_tables=True)SeeSQLAlchemy Sessions for detailed documentation.
Advanced SQLite sessions
Enhanced SQLite sessions with conversation branching, usage analytics, and structured queries:
fromagents.extensions.memoryimportAdvancedSQLiteSession# Create with advanced featuressession=AdvancedSQLiteSession(session_id="user_123",db_path="conversations.db",create_tables=True)# Automatic usage trackingresult=awaitRunner.run(agent,"Hello",session=session)awaitsession.store_run_usage(result)# Track token usage# Conversation branchingawaitsession.create_branch_from_turn(2)# Branch from turn 2SeeAdvanced SQLite Sessions for detailed documentation.
Encrypted sessions
Transparent encryption wrapper for any session implementation:
fromagents.extensions.memoryimportEncryptedSession,SQLAlchemySession# Create underlying sessionunderlying_session=SQLAlchemySession.from_url("user_123",url="sqlite+aiosqlite:///conversations.db",create_tables=True)# Wrap with encryption and TTLsession=EncryptedSession(session_id="user_123",underlying_session=underlying_session,encryption_key="your-secret-key",ttl=600# 10 minutes)result=awaitRunner.run(agent,"Hello",session=session)SeeEncrypted Sessions for detailed documentation.
Other session types
There are a few more built-in options. Please refer toexamples/memory/ and source code underextensions/memory/.
Session management
Session ID naming
Use meaningful session IDs that help you organize conversations:
- User-based:
"user_12345" - Thread-based:
"thread_abc123" - Context-based:
"support_ticket_456"
Memory persistence
- Use in-memory SQLite (
SQLiteSession("session_id")) for temporary conversations - Use file-based SQLite (
SQLiteSession("session_id", "path/to/db.sqlite")) for persistent conversations - Use SQLAlchemy-powered sessions (
SQLAlchemySession("session_id", engine=engine, create_tables=True)) for production systems with existing databases supported by SQLAlchemy - Use Dapr state store sessions (
DaprSession.from_address("session_id", state_store_name="statestore", dapr_address="localhost:50001")) for production cloud-native deployments with support for 30+ database backends with built-in telemetry, tracing, and data isolation - Use OpenAI-hosted storage (
OpenAIConversationsSession()) when you prefer to store history in the OpenAI Conversations API - Use encrypted sessions (
EncryptedSession(session_id, underlying_session, encryption_key)) to wrap any session with transparent encryption and TTL-based expiration - Consider implementing custom session backends for other production systems (Redis, Django, etc.) for more advanced use cases
Multiple sessions
fromagentsimportAgent,Runner,SQLiteSessionagent=Agent(name="Assistant")# Different sessions maintain separate conversation historiessession_1=SQLiteSession("user_123","conversations.db")session_2=SQLiteSession("user_456","conversations.db")result1=awaitRunner.run(agent,"Help me with my account",session=session_1)result2=awaitRunner.run(agent,"What are my charges?",session=session_2)Session sharing
# Different agents can share the same sessionsupport_agent=Agent(name="Support")billing_agent=Agent(name="Billing")session=SQLiteSession("user_123")# Both agents will see the same conversation historyresult1=awaitRunner.run(support_agent,"Help me with my account",session=session)result2=awaitRunner.run(billing_agent,"What are my charges?",session=session)Complete example
Here's a complete example showing session memory in action:
importasynciofromagentsimportAgent,Runner,SQLiteSessionasyncdefmain():# Create an agentagent=Agent(name="Assistant",instructions="Reply very concisely.",)# Create a session instance that will persist across runssession=SQLiteSession("conversation_123","conversation_history.db")print("=== Sessions Example ===")print("The agent will remember previous messages automatically.\n")# First turnprint("First turn:")print("User: What city is the Golden Gate Bridge in?")result=awaitRunner.run(agent,"What city is the Golden Gate Bridge in?",session=session)print(f"Assistant:{result.final_output}")print()# Second turn - the agent will remember the previous conversationprint("Second turn:")print("User: What state is it in?")result=awaitRunner.run(agent,"What state is it in?",session=session)print(f"Assistant:{result.final_output}")print()# Third turn - continuing the conversationprint("Third turn:")print("User: What's the population of that state?")result=awaitRunner.run(agent,"What's the population of that state?",session=session)print(f"Assistant:{result.final_output}")print()print("=== Conversation Complete ===")print("Notice how the agent remembered the context from previous turns!")print("Sessions automatically handles conversation history.")if__name__=="__main__":asyncio.run(main())Custom session implementations
You can implement your own session memory by creating a class that follows theSession protocol:
fromagents.memory.sessionimportSessionABCfromagents.itemsimportTResponseInputItemfromtypingimportListclassMyCustomSession(SessionABC):"""Custom session implementation following the Session protocol."""def__init__(self,session_id:str):self.session_id=session_id# Your initialization hereasyncdefget_items(self,limit:int|None=None)->List[TResponseInputItem]:"""Retrieve conversation history for this session."""# Your implementation herepassasyncdefadd_items(self,items:List[TResponseInputItem])->None:"""Store new items for this session."""# Your implementation herepassasyncdefpop_item(self)->TResponseInputItem|None:"""Remove and return the most recent item from this session."""# Your implementation herepassasyncdefclear_session(self)->None:"""Clear all items for this session."""# Your implementation herepass# Use your custom sessionagent=Agent(name="Assistant")result=awaitRunner.run(agent,"Hello",session=MyCustomSession("my_session"))Community session implementations
The community has developed additional session implementations:
| Package | Description |
|---|---|
| openai-django-sessions | Django ORM-based sessions for any Django-supported database (PostgreSQL, MySQL, SQLite, and more) |
If you've built a session implementation, please feel free to submit a documentation PR to add it here!
API Reference
For detailed API documentation, see:
Session- Protocol interfaceOpenAIConversationsSession- OpenAI Conversations API implementationSQLiteSession- Basic SQLite implementationSQLAlchemySession- SQLAlchemy-powered implementationDaprSession- Dapr state store implementationAdvancedSQLiteSession- Enhanced SQLite with branching and analyticsEncryptedSession- Encrypted wrapper for any session