Skip to content

Commit f2d0bd1

Browse files
committed
Introduce docs for AdvancedSQLiteSession and refactor sessions section in docs
1 parent 4c4b7c2 commit f2d0bd1

File tree

8 files changed

+724
-128
lines changed

8 files changed

+724
-128
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `AdvancedSQLiteSession`
2+
3+
::: agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `EncryptedSession`
2+
3+
::: agents.extensions.memory.encrypt_session.EncryptedSession

docs/ref/memory.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
members:
77
- Session
88
- SQLiteSession
9+
- OpenAIConversationsSession
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
# Advanced SQLite Sessions
2+
3+
`AdvancedSQLiteSession` is an enhanced version of the basic `SQLiteSession` that provides advanced conversation management capabilities including conversation branching, detailed usage analytics, and structured conversation queries.
4+
5+
## Features
6+
7+
- **Conversation branching**: Create alternative conversation paths from any user message
8+
- **Usage tracking**: Detailed token usage analytics per turn with full JSON breakdowns
9+
- **Structured queries**: Get conversations by turns, tool usage statistics, and more
10+
- **Branch management**: Independent branch switching and management
11+
- **Message structure metadata**: Track message types, tool usage, and conversation flow
12+
13+
## Quick start
14+
15+
```python
16+
from agents import Agent, Runner
17+
from agents.extensions.memory import AdvancedSQLiteSession
18+
19+
# Create agent
20+
agent = Agent(
21+
name="Assistant",
22+
instructions="Reply very concisely.",
23+
)
24+
25+
# Create an advanced session
26+
session = AdvancedSQLiteSession(
27+
session_id="conversation_123",
28+
db_path="conversations.db",
29+
create_tables=True
30+
)
31+
32+
# First conversation turn
33+
result = await Runner.run(
34+
agent,
35+
"What city is the Golden Gate Bridge in?",
36+
session=session
37+
)
38+
print(result.final_output) # "San Francisco"
39+
40+
# IMPORTANT: Store usage data
41+
await session.store_run_usage(result)
42+
43+
# Continue conversation
44+
result = await Runner.run(
45+
agent,
46+
"What state is it in?",
47+
session=session
48+
)
49+
print(result.final_output) # "California"
50+
await session.store_run_usage(result)
51+
```
52+
53+
## Initialization
54+
55+
```python
56+
from agents.extensions.memory import AdvancedSQLiteSession
57+
58+
# Basic initialization
59+
session = AdvancedSQLiteSession(
60+
session_id="my_conversation",
61+
create_tables=True # Auto-create advanced tables
62+
)
63+
64+
# With persistent storage
65+
session = AdvancedSQLiteSession(
66+
session_id="user_123",
67+
db_path="path/to/conversations.db",
68+
create_tables=True
69+
)
70+
71+
# With custom logger
72+
import logging
73+
logger = logging.getLogger("my_app")
74+
session = AdvancedSQLiteSession(
75+
session_id="session_456",
76+
create_tables=True,
77+
logger=logger
78+
)
79+
```
80+
81+
### Parameters
82+
83+
- `session_id` (str): Unique identifier for the conversation session
84+
- `db_path` (str | Path): Path to SQLite database file. Defaults to `:memory:` for in-memory storage
85+
- `create_tables` (bool): Whether to automatically create the advanced tables. Defaults to `False`
86+
- `logger` (logging.Logger | None): Custom logger for the session. Defaults to module logger
87+
88+
## Usage tracking
89+
90+
AdvancedSQLiteSession provides detailed usage analytics by storing token usage data per conversation turn. **This is entirely dependent on the `store_run_usage` method being called after each agent run.**
91+
92+
### Storing usage data
93+
94+
```python
95+
# After each agent run, store the usage data
96+
result = await Runner.run(agent, "Hello", session=session)
97+
await session.store_run_usage(result)
98+
99+
# This stores:
100+
# - Total tokens used
101+
# - Input/output token breakdown
102+
# - Request count
103+
# - Detailed JSON token information (if available)
104+
```
105+
106+
### Retrieving usage statistics
107+
108+
```python
109+
# Get session-level usage (all branches)
110+
session_usage = await session.get_session_usage()
111+
if session_usage:
112+
print(f"Total requests: {session_usage['requests']}")
113+
print(f"Total tokens: {session_usage['total_tokens']}")
114+
print(f"Input tokens: {session_usage['input_tokens']}")
115+
print(f"Output tokens: {session_usage['output_tokens']}")
116+
print(f"Total turns: {session_usage['total_turns']}")
117+
118+
# Get usage for specific branch
119+
branch_usage = await session.get_session_usage(branch_id="main")
120+
121+
# Get usage by turn
122+
turn_usage = await session.get_turn_usage()
123+
for turn_data in turn_usage:
124+
print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens")
125+
if turn_data['input_tokens_details']:
126+
print(f" Input details: {turn_data['input_tokens_details']}")
127+
if turn_data['output_tokens_details']:
128+
print(f" Output details: {turn_data['output_tokens_details']}")
129+
130+
# Get usage for specific turn
131+
turn_2_usage = await session.get_turn_usage(user_turn_number=2)
132+
```
133+
134+
## Conversation branching
135+
136+
One of the key features of AdvancedSQLiteSession is the ability to create conversation branches from any user message, allowing you to explore alternative conversation paths.
137+
138+
### Creating branches
139+
140+
```python
141+
# Get available turns for branching
142+
turns = await session.get_conversation_turns()
143+
for turn in turns:
144+
print(f"Turn {turn['turn']}: {turn['content']}")
145+
print(f"Can branch: {turn['can_branch']}")
146+
147+
# Create a branch from turn 2
148+
branch_id = await session.create_branch_from_turn(2)
149+
print(f"Created branch: {branch_id}")
150+
151+
# Create a branch with custom name
152+
branch_id = await session.create_branch_from_turn(
153+
2,
154+
branch_name="alternative_path"
155+
)
156+
157+
# Create branch by searching for content
158+
branch_id = await session.create_branch_from_content(
159+
"weather",
160+
branch_name="weather_focus"
161+
)
162+
```
163+
164+
### Branch management
165+
166+
```python
167+
# List all branches
168+
branches = await session.list_branches()
169+
for branch in branches:
170+
current = " (current)" if branch["is_current"] else ""
171+
print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}")
172+
173+
# Switch between branches
174+
await session.switch_to_branch("main")
175+
await session.switch_to_branch(branch_id)
176+
177+
# Delete a branch
178+
await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch
179+
```
180+
181+
### Branch workflow example
182+
183+
```python
184+
# Original conversation
185+
result = await Runner.run(agent, "What's the capital of France?", session=session)
186+
await session.store_run_usage(result)
187+
188+
result = await Runner.run(agent, "What's the weather like there?", session=session)
189+
await session.store_run_usage(result)
190+
191+
# Create branch from turn 2 (weather question)
192+
branch_id = await session.create_branch_from_turn(2, "weather_focus")
193+
194+
# Continue in new branch with different question
195+
result = await Runner.run(
196+
agent,
197+
"What are the main tourist attractions in Paris?",
198+
session=session
199+
)
200+
await session.store_run_usage(result)
201+
202+
# Switch back to main branch
203+
await session.switch_to_branch("main")
204+
205+
# Continue original conversation
206+
result = await Runner.run(
207+
agent,
208+
"How expensive is it to visit?",
209+
session=session
210+
)
211+
await session.store_run_usage(result)
212+
```
213+
214+
## Structured queries
215+
216+
AdvancedSQLiteSession provides several methods for analyzing conversation structure and content.
217+
218+
### Conversation analysis
219+
220+
```python
221+
# Get conversation organized by turns
222+
conversation_by_turns = await session.get_conversation_by_turns()
223+
for turn_num, items in conversation_by_turns.items():
224+
print(f"Turn {turn_num}: {len(items)} items")
225+
for item in items:
226+
if item["tool_name"]:
227+
print(f" - {item['type']} (tool: {item['tool_name']})")
228+
else:
229+
print(f" - {item['type']}")
230+
231+
# Get tool usage statistics
232+
tool_usage = await session.get_tool_usage()
233+
for tool_name, count, turn in tool_usage:
234+
print(f"{tool_name}: used {count} times in turn {turn}")
235+
236+
# Find turns by content
237+
matching_turns = await session.find_turns_by_content("weather")
238+
for turn in matching_turns:
239+
print(f"Turn {turn['turn']}: {turn['content']}")
240+
```
241+
242+
### Message structure
243+
244+
The session automatically tracks message structure including:
245+
246+
- Message types (user, assistant, tool_call, etc.)
247+
- Tool names for tool calls
248+
- Turn numbers and sequence numbers
249+
- Branch associations
250+
- Timestamps
251+
252+
## Database schema
253+
254+
AdvancedSQLiteSession extends the basic SQLite schema with two additional tables:
255+
256+
### message_structure table
257+
258+
```sql
259+
CREATE TABLE message_structure (
260+
id INTEGER PRIMARY KEY AUTOINCREMENT,
261+
session_id TEXT NOT NULL,
262+
message_id INTEGER NOT NULL,
263+
branch_id TEXT NOT NULL DEFAULT 'main',
264+
message_type TEXT NOT NULL,
265+
sequence_number INTEGER NOT NULL,
266+
user_turn_number INTEGER,
267+
branch_turn_number INTEGER,
268+
tool_name TEXT,
269+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
270+
FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE,
271+
FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE
272+
);
273+
```
274+
275+
### turn_usage table
276+
277+
```sql
278+
CREATE TABLE turn_usage (
279+
id INTEGER PRIMARY KEY AUTOINCREMENT,
280+
session_id TEXT NOT NULL,
281+
branch_id TEXT NOT NULL DEFAULT 'main',
282+
user_turn_number INTEGER NOT NULL,
283+
requests INTEGER DEFAULT 0,
284+
input_tokens INTEGER DEFAULT 0,
285+
output_tokens INTEGER DEFAULT 0,
286+
total_tokens INTEGER DEFAULT 0,
287+
input_tokens_details JSON,
288+
output_tokens_details JSON,
289+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
290+
FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE,
291+
UNIQUE(session_id, branch_id, user_turn_number)
292+
);
293+
```
294+
295+
## Complete example
296+
297+
Check out the [complete example](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py) for a comprehensive demonstration of all features.
298+
299+
300+
## API Reference
301+
302+
- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - Main class
303+
- [`Session`][agents.memory.session.Session] - Base session protocol

0 commit comments

Comments
 (0)