Persistent conversation history storage with multiple backend options.
Base interface for implementing conversation history storage.
/**
* Session interface for persistent conversation history
*/
interface Session {
/**
* Get unique session identifier
* @returns Session ID
*/
getSessionId(): Promise<string>;
/**
* Get conversation history items
* @param limit - Maximum number of items to return
* @returns Array of agent input items
*/
getItems(limit?: number): Promise<AgentInputItem[]>;
/**
* Add new items to the session history
* @param items - Items to add
*/
addItems(items: AgentInputItem[]): Promise<void>;
/**
* Remove and return the last item from history
* @returns Last item or undefined if empty
*/
popItem(): Promise<AgentInputItem | undefined>;
/**
* Clear all session history
*/
clearSession(): Promise<void>;
}Usage Examples:
import { Agent, run, Session } from '@openai/agents';
// Using a session with run
class CustomSession implements Session {
private items: AgentInputItem[] = [];
private sessionId: string = 'session-' + Date.now();
async getSessionId(): Promise<string> {
return this.sessionId;
}
async getItems(limit?: number): Promise<AgentInputItem[]> {
if (limit) {
return this.items.slice(-limit);
}
return this.items;
}
async addItems(items: AgentInputItem[]): Promise<void> {
this.items.push(...items);
}
async popItem(): Promise<AgentInputItem | undefined> {
return this.items.pop();
}
async clearSession(): Promise<void> {
this.items = [];
}
}
const session = new CustomSession();
const agent = new Agent({
name: 'Assistant',
instructions: 'You are helpful',
});
// First message
const result1 = await run(agent, 'My name is Alice', { session });
console.log(result1.finalOutput);
// Second message (with history)
const result2 = await run(agent, 'What is my name?', { session });
console.log(result2.finalOutput); // Should remember "Alice"
// Check session history
const history = await session.getItems();
console.log('History items:', history.length);
// Clear session
await session.clearSession();In-memory session implementation for development and testing.
/**
* In-memory session implementation (not persistent)
* For development and testing only
*/
class MemorySession implements Session {
constructor(options?: MemorySessionOptions);
getSessionId(): Promise<string>;
getItems(limit?: number): Promise<AgentInputItem[]>;
addItems(items: AgentInputItem[]): Promise<void>;
popItem(): Promise<AgentInputItem | undefined>;
clearSession(): Promise<void>;
}
interface MemorySessionOptions {
/** Initial session ID */
sessionId?: string;
/** Initial history items */
initialItems?: AgentInputItem[];
}Usage Examples:
import { Agent, run, MemorySession } from '@openai/agents';
// Basic memory session
const session = new MemorySession();
const agent = new Agent({
name: 'ChatAgent',
instructions: 'You are a conversational assistant',
});
// Conversation with memory
const result1 = await run(agent, 'I like pizza', { session });
const result2 = await run(agent, 'What food do I like?', { session });
console.log(result2.finalOutput); // Should mention pizza
// Memory session with initial ID
const namedSession = new MemorySession({
sessionId: 'user-123-session',
});
// Memory session with initial history
import { user, assistant } from '@openai/agents';
const preloadedSession = new MemorySession({
initialItems: [
user('Hello'),
assistant('Hi! How can I help you?'),
user('Tell me about sessions'),
],
});
const result3 = await run(agent, 'Continue from where we left off', {
session: preloadedSession,
});
// Access session data
const sessionId = await session.getSessionId();
console.log('Session ID:', sessionId);
const history = await session.getItems();
console.log('History length:', history.length);
const limitedHistory = await session.getItems(5); // Last 5 items
console.log('Last 5 items:', limitedHistory.length);
// Modify session
const lastItem = await session.popItem();
console.log('Removed item:', lastItem);
await session.clearSession();
console.log('Session cleared');Session implementation using OpenAI's Conversations API for persistent storage.
/**
* Session backed by OpenAI Conversations API
* Provides persistent, scalable conversation storage
*/
class OpenAIConversationsSession implements Session {
constructor(options?: OpenAIConversationsSessionOptions);
getSessionId(): Promise<string>;
getItems(limit?: number): Promise<AgentInputItem[]>;
addItems(items: AgentInputItem[]): Promise<void>;
popItem(): Promise<AgentInputItem | undefined>;
clearSession(): Promise<void>;
}
interface OpenAIConversationsSessionOptions {
/** Existing conversation ID */
conversationId?: string;
/** OpenAI client instance */
client?: OpenAI;
/** API key (if not using client) */
apiKey?: string;
/** Base URL (if not using client) */
baseURL?: string;
/** Organization ID */
organization?: string;
/** Project ID */
project?: string;
}
/**
* Create a new conversation session and return its ID
* @param client - OpenAI client (optional)
* @returns Conversation ID string for the new session
*/
function startOpenAIConversationsSession(
client?: OpenAI
): Promise<string>;Usage Examples:
import { Agent, run, OpenAIConversationsSession, startOpenAIConversationsSession } from '@openai/agents';
import OpenAI from 'openai';
// Create new conversation (returns conversation ID)
const conversationId = await startOpenAIConversationsSession();
console.log('Conversation ID:', conversationId);
// Create session with the conversation ID
const session = new OpenAIConversationsSession({
conversationId,
});
const agent = new Agent({
name: 'PersistentAgent',
instructions: 'You are a helpful assistant with persistent memory',
});
// First conversation
const result1 = await run(agent, 'My favorite color is blue', { session });
// Resume existing conversation later (even from different process)
const resumedSession = new OpenAIConversationsSession({
conversationId,
});
const result2 = await run(agent, 'What is my favorite color?', {
session: resumedSession,
});
console.log(result2.finalOutput); // Should remember "blue"
// With custom OpenAI client
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
organization: 'org-123',
});
const customConversationId = await startOpenAIConversationsSession(client);
// With API key directly
const directSession = new OpenAIConversationsSession({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1',
});
// Access conversation history
const history = await session.getItems();
console.log('Full history:', history.length);
const recent = await session.getItems(10); // Last 10 items
console.log('Recent history:', recent.length);
// Clear conversation
await session.clearSession();Use sessions with the run function and Runner class.
interface RunOptions<TContext = any> {
/** Session for persistent conversation history */
session?: Session;
/** Other run options... */
}Usage Examples:
import { Agent, run, Runner, MemorySession } from '@openai/agents';
const session = new MemorySession();
const agent = new Agent({
name: 'ConversationalAgent',
instructions: 'You are conversational and remember context',
});
// With run function
const result1 = await run(agent, 'I live in Tokyo', { session });
const result2 = await run(agent, 'What city do I live in?', { session });
// With Runner instance
const runner = new Runner({
workflowName: 'SessionDemo',
});
const result3 = await runner.run(agent, 'My job is engineer', { session });
const result4 = await runner.run(agent, 'What is my job?', { session });
// Multiple sessions
const session1 = new MemorySession({ sessionId: 'user-1' });
const session2 = new MemorySession({ sessionId: 'user-2' });
await run(agent, 'My name is Alice', { session: session1 });
await run(agent, 'My name is Bob', { session: session2 });
const result5 = await run(agent, 'What is my name?', { session: session1 });
console.log(result5.finalOutput); // "Alice"
const result6 = await run(agent, 'What is my name?', { session: session2 });
console.log(result6.finalOutput); // "Bob"Customize how session history is loaded and processed.
interface RunnerConfig<TContext = any> {
/**
* Customize session history handling
* Called before each agent run with session
*/
sessionInputCallback?: SessionInputCallback;
}
type SessionInputCallback = (
input: AgentInputItem[],
session: Session
) => Promise<AgentInputItem[]>;Usage Examples:
import { Agent, Runner, MemorySession, AgentInputItem } from '@openai/agents';
// Limit session history
const runner = new Runner({
sessionInputCallback: async (input, session) => {
// Only keep last 20 messages
const history = await session.getItems();
return history.slice(-20);
},
});
const session = new MemorySession();
const agent = new Agent({
name: 'LimitedHistoryAgent',
instructions: 'You are helpful',
});
await runner.run(agent, 'Hello', { session });
// Filter session history
const filteringRunner = new Runner({
sessionInputCallback: async (input, session) => {
const history = await session.getItems();
// Remove system messages from history
return history.filter(item => item.type !== 'system_message');
},
});
// Transform session history
const transformRunner = new Runner({
sessionInputCallback: async (input, session) => {
const history = await session.getItems();
// Summarize old messages
if (history.length > 50) {
const summary = '... [Earlier conversation summarized] ...';
const recentHistory = history.slice(-30);
return [
{ type: 'system_message', content: summary } as AgentInputItem,
...recentHistory,
];
}
return history;
},
});Manipulate session history directly.
Usage Examples:
import { Agent, run, MemorySession, user, assistant } from '@openai/agents';
const session = new MemorySession();
// Pre-populate session
await session.addItems([
user('Hello'),
assistant('Hi! How can I help?'),
]);
const agent = new Agent({
name: 'Agent',
instructions: 'You are helpful',
});
// Continue from pre-populated history
const result = await run(agent, 'What did I say first?', { session });
console.log(result.finalOutput); // Should mention "Hello"
// Get history
const allHistory = await session.getItems();
console.log('Total items:', allHistory.length);
const lastThree = await session.getItems(3);
console.log('Last 3 items:', lastThree);
// Remove last item
const removed = await session.popItem();
console.log('Removed:', removed);
// Add multiple items
await session.addItems([
user('Additional message 1'),
user('Additional message 2'),
]);
// Clear everything
await session.clearSession();
const empty = await session.getItems();
console.log('After clear:', empty.length); // 0Build multi-turn conversations with session context.
Usage Examples:
import { Agent, run, MemorySession } from '@openai/agents';
const session = new MemorySession();
const agent = new Agent({
name: 'TravelAgent',
instructions: 'You are a travel booking assistant',
});
// Turn 1: Gather destination
const turn1 = await run(
agent,
'I want to book a trip',
{ session }
);
console.log(turn1.finalOutput); // "Where would you like to go?"
// Turn 2: Gather dates
const turn2 = await run(
agent,
'I want to go to Paris',
{ session }
);
console.log(turn2.finalOutput); // "When would you like to travel?"
// Turn 3: Gather preferences
const turn3 = await run(
agent,
'Next month from the 15th to the 20th',
{ session }
);
console.log(turn3.finalOutput); // "What type of accommodation?"
// Turn 4: Confirm
const turn4 = await run(
agent,
'A hotel near the Eiffel Tower',
{ session }
);
console.log(turn4.finalOutput); // Confirmation with all details
// Review complete conversation
const history = await session.getItems();
console.log('Conversation turns:', history.length);Common patterns for session storage.
Usage Examples:
import { Agent, run, OpenAIConversationsSession, MemorySession } from '@openai/agents';
// Pattern 1: Per-user sessions
const userSessions = new Map<string, OpenAIConversationsSession>();
async function getUserSession(userId: string): Promise<OpenAIConversationsSession> {
if (!userSessions.has(userId)) {
const session = await startOpenAIConversationsSession();
userSessions.set(userId, session);
}
return userSessions.get(userId)!;
}
const agent = new Agent({
name: 'UserAgent',
instructions: 'You are helpful',
});
const aliceSession = await getUserSession('alice');
await run(agent, 'Hello', { session: aliceSession });
// Pattern 2: Session expiry
class ExpiringSession implements Session {
private session: MemorySession;
private lastAccess: number;
private ttlMs: number = 30 * 60 * 1000; // 30 minutes
constructor() {
this.session = new MemorySession();
this.lastAccess = Date.now();
}
private checkExpiry() {
if (Date.now() - this.lastAccess > this.ttlMs) {
this.session.clearSession();
}
this.lastAccess = Date.now();
}
async getSessionId(): Promise<string> {
this.checkExpiry();
return this.session.getSessionId();
}
async getItems(limit?: number): Promise<AgentInputItem[]> {
this.checkExpiry();
return this.session.getItems(limit);
}
async addItems(items: AgentInputItem[]): Promise<void> {
this.checkExpiry();
return this.session.addItems(items);
}
async popItem(): Promise<AgentInputItem | undefined> {
this.checkExpiry();
return this.session.popItem();
}
async clearSession(): Promise<void> {
return this.session.clearSession();
}
}
// Pattern 3: Database-backed session
import { Database } from 'some-database-library';
class DatabaseSession implements Session {
private db: Database;
private sessionId: string;
constructor(db: Database, sessionId: string) {
this.db = db;
this.sessionId = sessionId;
}
async getSessionId(): Promise<string> {
return this.sessionId;
}
async getItems(limit?: number): Promise<AgentInputItem[]> {
const query = limit
? `SELECT * FROM session_history WHERE session_id = ? ORDER BY created_at DESC LIMIT ?`
: `SELECT * FROM session_history WHERE session_id = ? ORDER BY created_at ASC`;
const params = limit ? [this.sessionId, limit] : [this.sessionId];
const rows = await this.db.query(query, params);
return rows.map(row => JSON.parse(row.item_data));
}
async addItems(items: AgentInputItem[]): Promise<void> {
const query = `INSERT INTO session_history (session_id, item_data, created_at) VALUES (?, ?, ?)`;
for (const item of items) {
await this.db.execute(query, [
this.sessionId,
JSON.stringify(item),
Date.now(),
]);
}
}
async popItem(): Promise<AgentInputItem | undefined> {
const items = await this.getItems(1);
if (items.length === 0) return undefined;
await this.db.execute(
`DELETE FROM session_history WHERE session_id = ? ORDER BY created_at DESC LIMIT 1`,
[this.sessionId]
);
return items[0];
}
async clearSession(): Promise<void> {
await this.db.execute(
`DELETE FROM session_history WHERE session_id = ?`,
[this.sessionId]
);
}
}Use sessions with streaming responses.
Usage Examples:
import { Agent, run, MemorySession } from '@openai/agents';
const session = new MemorySession();
const agent = new Agent({
name: 'StreamingAgent',
instructions: 'You are helpful',
});
// First message with streaming
const stream1 = run(agent, 'Tell me a story', {
session,
stream: true,
});
for await (const event of stream1) {
if (event.type === 'message_output_created') {
process.stdout.write(event.item.message.content);
}
}
await stream1.completed;
// Second message with streaming (includes history)
const stream2 = run(agent, 'Continue the story', {
session,
stream: true,
});
for await (const event of stream2) {
if (event.type === 'message_output_created') {
process.stdout.write(event.item.message.content);
}
}
await stream2.completed;
// Check accumulated history
const history = await session.getItems();
console.log('Messages in session:', history.length);