Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6b94ad0

Browse files
Add Sessions for Automatic Conversation History Management (openai#752)
# Overview Resolves openai#745 This PR introduces **Sessions**, a new core feature that automatically maintains conversation history across multiple agent runs, eliminating the need to manually handle `.to_input_list()` between turns. ## Key Features ### 🧠 Automatic Memory Management - **Zero-effort conversation continuity**: Agents automatically remember previous context without manual state management - **Session-based organization**: Each conversation is isolated by unique session IDs - **Seamless integration**: Works with existing `Runner.run()`, `Runner.run_sync()`, and `Runner.run_streamed()` methods ### 🔌 Extensible Session Protocol - **Library-agnostic design**: Clean protocol interface allows any storage backend - **Drop-in implementations**: Easy integration with Redis, PostgreSQL, MongoDB, or any custom storage - **Production-ready interface**: Async-first design with proper error handling and type safety - **Vendor flexibility**: Library authors can provide their own Session implementations ### 💾 Built-in SQLite Implementation - **In-memory SQLite**: Perfect for temporary conversations during development - **Persistent SQLite**: File-based storage for conversations that survive application restarts - **Thread-safe operations**: Production-ready with connection pooling and proper concurrency handling ### 🔧 Simple API ```python # Before: Manual conversation management result1 = await Runner.run(agent, "What's the weather?") new_input = result1.to_input_list() + [{"role": "user", "content": "How about tomorrow?"}] result2 = await Runner.run(agent, new_input) # After: Automatic with Sessions session = SQLiteSession("user_123") result1 = await Runner.run(agent, "What's the weather?", session=session) result2 = await Runner.run(agent, "How about tomorrow?", session=session) # Remembers context automatically ``` ## What's Included ### Core Session Protocol - **`Session` Protocol**: Clean, async interface that any storage backend can implement - **Type-safe design**: Full type hints and runtime validation - **Standard operations**: `get_items()`, `add_items()`, `pop_item()`, `clear_session()` - **Extensibility-first**: Designed for third-party implementations ### Reference Implementation - **`SQLiteSession` Class**: Production-ready SQLite implementation - **Automatic schema management**: Creates tables and indexes automatically - **Connection pooling**: Thread-safe operations with proper resource management - **Flexible storage**: In-memory or persistent file-based databases ### Runner Integration - **New `session` parameter**: Drop-in addition to existing `Runner` methods - **Backward compatibility**: Zero breaking changes to existing code - **Automatic history management**: Prepends conversation history before each run ## Session Protocol for Library Authors The Session protocol provides a clean interface for implementing custom storage backends: ```python from agents.memory import Session from typing import List class MyCustomSession: """Custom session implementation following the Session protocol.""" def __init__(self, session_id: str): self.session_id = session_id # Your initialization here async def get_items(self, limit: int | None = None) -> List[dict]: """Retrieve conversation history for this session.""" # Your implementation here pass async def add_items(self, items: List[dict]) -> None: """Store new items for this session.""" # Your implementation here pass async def pop_item(self) -> dict | None: """Remove and return the most recent item from this session.""" # Your implementation here pass async def clear_session(self) -> None: """Clear all items for this session.""" # Your implementation here pass # Works seamlessly with any custom implementation result = await Runner.run(agent, "Hello", session=MyCustomSession("session_123")) ``` ### Example Third-Party Implementations ```python # Redis-based session (hypothetical library implementation) from redis_sessions import RedisSession session = RedisSession("user_123", redis_url="redis://localhost:6379") # PostgreSQL-based session (hypothetical library implementation) from postgres_sessions import PostgreSQLSession session = PostgreSQLSession("user_123", connection_string="postgresql://...") # Cloud-based session (hypothetical library implementation) from cloud_sessions import CloudSession session = CloudSession("user_123", api_key="...", region="us-east-1") # All work identically with the Runner result = await Runner.run(agent, "Hello", session=session) ``` ## Benefits ### For Application Developers - **Reduces boilerplate**: No more manual `.to_input_list()` management - **Prevents memory leaks**: Automatic cleanup and organized storage - **Easier debugging**: Clear conversation history tracking - **Flexible storage**: Choose the right backend for your needs ### For Library Authors - **Clean integration**: Simple protocol to implement for any storage backend - **Type safety**: Full type hints and runtime validation - **Async-first**: Modern async/await design throughout - **Documentation**: Comprehensive examples and API reference ### For Applications - **Better user experience**: Seamless conversation continuity - **Scalable architecture**: Support for multiple concurrent conversations - **Flexible deployment**: In-memory for development, production storage for scale - **Multi-agent support**: Same conversation history can be shared across different agents ## Usage Examples ### Basic Usage with SQLiteSession ```python from agents import Agent, Runner, SQLiteSession agent = Agent(name="Assistant", instructions="Reply concisely.") session = SQLiteSession("conversation_123") # Conversation flows naturally await Runner.run(agent, "Hi, I'm planning a trip to Japan", session=session) await Runner.run(agent, "What's the best time to visit?", session=session) await Runner.run(agent, "How about cherry blossom season?", session=session) ``` ### Multiple Sessions with Isolation ```python # Different users get separate conversation histories session_alice = SQLiteSession("user_alice") session_bob = SQLiteSession("user_bob") # Completely isolated conversations await Runner.run(agent, "I like pizza", session=session_alice) await Runner.run(agent, "I like sushi", session=session_bob) ``` ### Persistent vs In-Memory Storage ```python # In-memory database (lost when process ends) session = SQLiteSession("user_123") # Persistent file-based database session = SQLiteSession("user_123", "conversations.db") ``` ### Session Management Operations ```python session = SQLiteSession("user_123") # Get all items in a session items = await session.get_items() # Add new items to a session new_items = [ {"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there!"} ] await session.add_items(new_items) # Remove and return the most recent item (useful for corrections) last_item = await session.pop_item() # Clear all items from a session await session.clear_session() ``` ### Message Correction Pattern ```python # User wants to correct their last question user_message = await session.pop_item() # Remove user's question assistant_message = await session.pop_item() # Remove agent's response # Ask a corrected question result = await Runner.run( agent, "What's 2 + 3?", # Corrected question session=session ) ``` ## Technical Details ### Session Protocol Design - **Async-first**: All operations are async for non-blocking I/O - **Type-safe**: Full type hints with runtime validation - **Error handling**: Graceful degradation and detailed error messages - **Resource management**: Proper cleanup and connection handling ### SQLiteSession Implementation - **Thread-safe operations** with connection pooling - **Automatic schema management** with proper indexing - **JSON serialization** for message storage - **Memory-efficient** conversation retrieval and storage - **Cross-platform compatibility** ## Breaking Changes None. This is a purely additive feature that doesn't affect existing functionality. ## Documentation - Updated core concepts in `docs/index.md` to highlight Sessions as a key primitive - New comprehensive guide at `docs/sessions.md` with protocol implementation examples - Enhanced `docs/running_agents.md` with automatic vs manual conversation management - Full API reference integration via `docs/ref/memory.md` - Implementation guide for library authors Sessions represent a significant architectural improvement for building conversational AI applications with the Agents SDK. The extensible Session protocol enables the ecosystem to provide specialized storage backends while maintaining a consistent, simple API for application developers. --------- Co-authored-by: Rohan Mehta <[email protected]>
1 parent db85a6d commit 6b94ad0

21 files changed

+1462
-33
lines changed

README.md

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,119 @@ The OpenAI Agents SDK is a lightweight yet powerful framework for building multi
1212
1. [**Agents**](https://openai.github.io/openai-agents-python/agents): LLMs configured with instructions, tools, guardrails, and handoffs
1313
2. [**Handoffs**](https://openai.github.io/openai-agents-python/handoffs/): A specialized tool call used by the Agents SDK for transferring control between agents
1414
3. [**Guardrails**](https://openai.github.io/openai-agents-python/guardrails/): Configurable safety checks for input and output validation
15-
4. [**Tracing**](https://openai.github.io/openai-agents-python/tracing/): Built-in tracking of agent runs, allowing you to view, debug and optimize your workflows
15+
4. [**Sessions**](#sessions): Automatic conversation history management across agent runs
16+
5. [**Tracing**](https://openai.github.io/openai-agents-python/tracing/): Built-in tracking of agent runs, allowing you to view, debug and optimize your workflows
1617

1718
Explore the [examples](examples) directory to see the SDK in action, and read our [documentation](https://openai.github.io/openai-agents-python/) for more details.
1819

20+
## Sessions
21+
22+
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.
23+
24+
### Quick start
25+
26+
```python
27+
from agents import Agent, Runner, SQLiteSession
28+
29+
# Create agent
30+
agent = Agent(
31+
name="Assistant",
32+
instructions="Reply very concisely.",
33+
)
34+
35+
# Create a session instance
36+
session = SQLiteSession("conversation_123")
37+
38+
# First turn
39+
result = await Runner.run(
40+
agent,
41+
"What city is the Golden Gate Bridge in?",
42+
session=session
43+
)
44+
print(result.final_output) # "San Francisco"
45+
46+
# Second turn - agent automatically remembers previous context
47+
result = await Runner.run(
48+
agent,
49+
"What state is it in?",
50+
session=session
51+
)
52+
print(result.final_output) # "California"
53+
54+
# Also works with synchronous runner
55+
result = Runner.run_sync(
56+
agent,
57+
"What's the population?",
58+
session=session
59+
)
60+
print(result.final_output) # "Approximately 39 million"
61+
```
62+
63+
### Session options
64+
65+
- **No memory** (default): No session memory when session parameter is omitted
66+
- **`session: Session = DatabaseSession(...)`**: Use a Session instance to manage conversation history
67+
68+
```python
69+
from agents import Agent, Runner, SQLiteSession
70+
71+
# Custom SQLite database file
72+
session = SQLiteSession("user_123", "conversations.db")
73+
agent = Agent(name="Assistant")
74+
75+
# Different session IDs maintain separate conversation histories
76+
result1 = await Runner.run(
77+
agent,
78+
"Hello",
79+
session=session
80+
)
81+
result2 = await Runner.run(
82+
agent,
83+
"Hello",
84+
session=SQLiteSession("user_456", "conversations.db")
85+
)
86+
```
87+
88+
### Custom session implementations
89+
90+
You can implement your own session memory by creating a class that follows the `Session` protocol:
91+
92+
```python
93+
from agents.memory import Session
94+
from typing import List
95+
96+
class MyCustomSession:
97+
"""Custom session implementation following the Session protocol."""
98+
99+
def __init__(self, session_id: str):
100+
self.session_id = session_id
101+
# Your initialization here
102+
103+
async def get_items(self, limit: int | None = None) -> List[dict]:
104+
# Retrieve conversation history for the session
105+
pass
106+
107+
async def add_items(self, items: List[dict]) -> None:
108+
# Store new items for the session
109+
pass
110+
111+
async def pop_item(self) -> dict | None:
112+
# Remove and return the most recent item from the session
113+
pass
114+
115+
async def clear_session(self) -> None:
116+
# Clear all items for the session
117+
pass
118+
119+
# Use your custom session
120+
agent = Agent(name="Assistant")
121+
result = await Runner.run(
122+
agent,
123+
"Hello",
124+
session=MyCustomSession("my_session")
125+
)
126+
```
127+
19128
## Get started
20129

21130
1. Set up your Python environment

docs/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ The [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) enables
55
- **Agents**, which are LLMs equipped with instructions and tools
66
- **Handoffs**, which allow agents to delegate to other agents for specific tasks
77
- **Guardrails**, which enable the inputs to agents to be validated
8+
- **Sessions**, which automatically maintains conversation history across agent runs
89

910
In combination with Python, these primitives are powerful enough to express complex relationships between tools and agents, and allow you to build real-world applications without a steep learning curve. In addition, the SDK comes with built-in **tracing** that lets you visualize and debug your agentic flows, as well as evaluate them and even fine-tune models for your application.
1011

@@ -21,6 +22,7 @@ Here are the main features of the SDK:
2122
- Python-first: Use built-in language features to orchestrate and chain agents, rather than needing to learn new abstractions.
2223
- Handoffs: A powerful feature to coordinate and delegate between multiple agents.
2324
- Guardrails: Run input validations and checks in parallel to your agents, breaking early if the checks fail.
25+
- Sessions: Automatic conversation history management across agent runs, eliminating manual state handling.
2426
- Function tools: Turn any Python function into a tool, with automatic schema generation and Pydantic-powered validation.
2527
- Tracing: Built-in tracing that lets you visualize, debug and monitor your workflows, as well as use the OpenAI suite of evaluation, fine-tuning and distillation tools.
2628

docs/ref/memory.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Memory
2+
3+
::: agents.memory
4+
5+
options:
6+
members:
7+
- Session
8+
- SQLiteSession

docs/running_agents.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ Calling any of the run methods can result in one or more agents running (and hen
6565

6666
At the end of the agent run, you can choose what to show to the user. For example, you might show the user every new item generated by the agents, or just the final output. Either way, the user might then ask a followup question, in which case you can call the run method again.
6767

68-
You can use the base [`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] method to get the inputs for the next turn.
68+
### Manual conversation management
69+
70+
You can manually manage conversation history using the [`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] method to get the inputs for the next turn:
6971

7072
```python
7173
async def main():
@@ -84,6 +86,39 @@ async def main():
8486
# California
8587
```
8688

89+
### Automatic conversation management with Sessions
90+
91+
For a simpler approach, you can use [Sessions](sessions.md) to automatically handle conversation history without manually calling `.to_input_list()`:
92+
93+
```python
94+
from agents import Agent, Runner, SQLiteSession
95+
96+
async def main():
97+
agent = Agent(name="Assistant", instructions="Reply very concisely.")
98+
99+
# Create session instance
100+
session = SQLiteSession("conversation_123")
101+
102+
with trace(workflow_name="Conversation", group_id=thread_id):
103+
# First turn
104+
result = await Runner.run(agent, "What city is the Golden Gate Bridge in?", session=session)
105+
print(result.final_output)
106+
# San Francisco
107+
108+
# Second turn - agent automatically remembers previous context
109+
result = await Runner.run(agent, "What state is it in?", session=session)
110+
print(result.final_output)
111+
# California
112+
```
113+
114+
Sessions automatically:
115+
116+
- Retrieves conversation history before each run
117+
- Stores new messages after each run
118+
- Maintains separate conversations for different session IDs
119+
120+
See the [Sessions documentation](sessions.md) for more details.
121+
87122
## Exceptions
88123

89124
The SDK raises exceptions in certain cases. The full list is in [`agents.exceptions`][]. As an overview:

docs/scripts/translate_docs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,9 @@ def translate_single_source_file(file_path: str) -> None:
266266

267267
def main():
268268
parser = argparse.ArgumentParser(description="Translate documentation files")
269-
parser.add_argument("--file", type=str, help="Specific file to translate (relative to docs directory)")
269+
parser.add_argument(
270+
"--file", type=str, help="Specific file to translate (relative to docs directory)"
271+
)
270272
args = parser.parse_args()
271273

272274
if args.file:

0 commit comments

Comments
 (0)