How to Handle Agent Context and State in OpenAI SDK: Complete Implementation Guide

The OpenAI Agents SDK provides automatic session persistence via SQLiteSession for turn-by-turn memory and manual threading via result.to_input_list() for fine-grained control over conversation history.

The awesome-llm-apps repository demonstrates production-ready patterns for managing agent context and state across the OpenAI SDK crash course and real-world agent implementations. Whether you need persistent multi-user chat history or custom conversation pruning, the SDK offers both high-level automation and low-level control.

Automatic Session Management with SQLiteSession

The OpenAI Agents SDK implements automatic context injection through the BaseSession interface, with SQLiteSession providing persistent storage out of the box.

Basic Session Usage

In ai_agent_framework_crash_course/openai_sdk_crash_course/7_sessions/streamlit_sessions_app.py, the SessionManager wraps SQLiteSession to provide high-level helpers:

from agents import Agent, Runner, SQLiteSession
import asyncio

# Initialize agent

assistant = Agent(
    name="HelpBot",
    instructions="You are a friendly assistant. Remember prior user messages."
)

# Create or fetch persistent session

session = SQLiteSession(session_id="help_chat", db_file="help_chat.db")

# Run with automatic context injection

result = asyncio.run(Runner.run(assistant, "How do I reset my password?", session=session))

The SDK automatically retrieves prior messages from the SQLite database and prepends them to the LLM request. All turns are stored with role and content fields for reconstruction.

Memory Operations

The session object exposes CRUD-style async methods for manipulating conversation state:

Method Description
get_items(limit=None) Return stored turns as dictionaries with role and content.
add_items(items) Append custom items (e.g., corrective system prompts).
pop_item() Remove the most recent turn for "undo" functionality.
clear_session() Delete the database and wipe conversation history.

To inject a corrective system message mid-conversation:

custom_items = [
    {"role": "system", "content": "Ignore the previous request; start over."}
]
await session.add_items(custom_items)

Manual Context Threading

For scenarios requiring fine-grained control over token limits or custom pruning strategies, the SDK supports manual conversation threading via result.to_input_list().

Pruning and Customizing Conversation History

In ai_agent_framework_crash_course/openai_sdk_crash_course/4_running_agents/agent_runner.py, the manual threading pattern allows explicit state management:


# Maintain conversation state in application memory

if "manual_conversation" not in st.session_state:
    st.session_state.manual_conversation = []

# Prune to last 10 turns to manage token limits

if len(st.session_state.manual_conversation) > 10:
    st.session_state.manual_conversation = st.session_state.manual_conversation[-10:]

# Build input list for current turn

input_list = st.session_state.manual_conversation.copy()
input_list.append({"role": "user", "content": query})

# Execute without automatic session (pass list directly)

result = asyncio.run(Runner.run(agent, input_list))

# Store full returned list for next iteration

st.session_state.manual_conversation = result.to_input_list()

The to_input_list() method returns exactly what was sent to the model, enabling you to:

  • Inject new system messages between turns
  • Merge multiple conversation streams
  • Implement custom summarization before the next call

Multi-Session and Handoff Patterns

The SessionManager abstraction supports complex deployment scenarios including isolated user memory and agent handoffs.

Isolated User Sessions

For multi-tenant applications, create separate SQLite files per user to ensure data isolation:

def get_user_session(user_id: str):
    db_name = f"user_{user_id}.db"
    return st.session_state.session_manager.get_session(user_id, db_name)

# Alice's isolated session

alice_session = get_user_session("alice")
alice_reply = asyncio.run(Runner.run(support_agent, "I can't login", session=alice_session))

Shared Sessions for Agent Handoffs

To transfer a conversation between specialized agents without losing context, use a shared database file:


# Initialize shared session

shared = st.session_state.session_manager.get_session("handoff_demo", "shared.db")

# First agent handles technical support

first = asyncio.run(Runner.run(support_agent, "My subscription is broken", session=shared))

# Hand off to sales agent using same session

second = asyncio.run(Runner.run(sales_agent, "Can I upgrade?", session=shared))

# Both interactions persist in shared.db with full continuity

Key Implementation Files

The awesome-llm-apps repository contains reference implementations demonstrating these patterns:

File Implementation Focus
ai_agent_framework_crash_course/openai_sdk_crash_course/7_sessions/streamlit_sessions_app.py SessionManager, SQLite persistence, memory operations (add_items, pop_item), multi-session and handoff patterns.
ai_agent_framework_crash_course/openai_sdk_crash_course/4_running_agents/agent_runner.py Manual threading with to_input_list(), async/sync/streaming execution modes, conversation pruning.
voice_ai_agents/voice_rag_openaisdk/rag_voice.py Custom context construction mixing retrieved documents with user input before passing to Runner.run.
starter_ai_agents/web_scrapping_ai_agent/ai_scrapper.py Stateless single-run pattern without session management for simple request-response workflows.

Summary

  • Automatic persistence: Use SQLiteSession with Runner.run() to store conversation history in a SQLite database without manual list management.
  • Manual control: Use result.to_input_list() to extract, modify, and prune conversation history before the next turn when you need custom token management.
  • Memory operations: Leverage session methods add_items(), pop_item(), and clear_session() to programmatically manipulate conversation state.
  • Multi-tenancy: Create isolated sessions per user with separate database files, or use shared sessions for agent handoffs while maintaining conversation continuity.

Frequently Asked Questions

What is the difference between SQLiteSession and manual threading in the OpenAI SDK?

SQLiteSession provides automatic persistence by storing each conversation turn in a SQLite database and automatically prepending history to subsequent requests. Manual threading requires you to maintain the conversation list in application memory using result.to_input_list(), giving you explicit control over pruning, injection of system messages, and custom history manipulation. Use SQLiteSession for standard chat persistence and manual threading when you need fine-grained control over the prompt construction.

How do I implement multi-user isolation with the OpenAI Agents SDK?

Create separate SQLite database files for each user by parameterizing the db_file argument in SQLiteSession. Map each user ID to a unique database file (e.g., user_{user_id}.db) using a SessionManager helper. This ensures conversation histories are physically isolated on disk while using the same session management logic. The awesome-llm-apps repository demonstrates this pattern in the multi-session demo where each user maintains independent persistent memory.

Can I transfer a conversation between different agents without losing context?

Yes, by using a shared session with a common database file. Initialize a SQLiteSession with the same session_id and db_file parameters, then pass this session to Runner.run() for different agent instances. The first agent's responses are persisted to the shared database, and when the second agent runs with the same session, it automatically receives the full conversation history. This enables seamless handoffs between specialized agents (e.g., from support to sales) while maintaining conversational continuity.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →