How to Set Up Conversation Memory with SQLite for Agents: OpenAI SDK and Google ADK Guide

You can set up conversation memory with SQLite for agents by using SQLiteSession in the OpenAI Agents SDK or DatabaseSessionService in Google ADK, both of which automatically persist conversation history to local SQLite files and reload it on subsequent runs.

Setting up conversation memory with SQLite for agents ensures your LLM applications retain context across user sessions and system restarts. The Shubhamsaboo/awesome-llm-apps repository provides production-ready implementations using the OpenAI Agents SDK and Google Agent Development Kit (ADK), demonstrating how to persist conversation state using lightweight, file-based SQLite databases without external infrastructure.

Why Use SQLite for Agent Conversation Memory?

SQLite provides a serverless, zero-configuration database engine that stores data in a single file on disk. For agent frameworks, this means you can maintain ACID-compliant conversation history without deploying PostgreSQL or Redis. Both the OpenAI Agents SDK and Google ADK leverage SQLite to store message threads, agent states, and event logs, enabling true persistence across process restarts.

OpenAI Agents SDK: Persistent Memory with SQLiteSession

The OpenAI Agents SDK implements conversation memory through the SQLiteSession class, which wraps a SQLite database to store message history. When you pass a SQLiteSession instance to Runner.run(), the SDK automatically appends each turn to the underlying database and retrieves the full history on subsequent calls.

Implementation Details

In ai_agent_framework_crash_course/openai_sdk_crash_course/7_sessions/7_1_basic_sessions/agent.py, the implementation demonstrates two modes:

  • In-memory sessions: Omit the db_path parameter to store history temporarily during the process lifetime
  • Persistent sessions: Provide a file path like "conversation_history.db" to survive process restarts

The SQLiteSession constructor signature is SQLiteSession(session_id, db_path=None), where session_id uniquely identifies the conversation thread.

Code Example

from agents import Agent, Runner, SQLiteSession
import asyncio

# Define the agent

root_agent = Agent(
    name="Memory Assistant",
    instructions="You are a helpful assistant that remembers prior conversation."
)

async def demo_persistent_memory():
    # Persistent SQLite session that survives restarts

    session = SQLiteSession("user_123", "chat_history.db")
    
    # First turn - stores to SQLite

    result1 = await Runner.run(
        root_agent, 
        "My name is Alice and I love hiking.", 
        session=session
    )
    print(f"Assistant: {result1.final_output}")
    
    # Second turn - automatically loads history from SQLite

    result2 = await Runner.run(
        root_agent, 
        "What is my name and what do I love?", 
        session=session
    )
    print(f"Assistant: {result2.final_output}")

# Run the demo

asyncio.run(demo_persistent_memory())

Google ADK: DatabaseSessionService for SQLite Persistence

Google's Agent Development Kit (ADK) provides the DatabaseSessionService class for persistent conversation storage. Unlike the OpenAI SDK's single-table approach, ADK creates three distinct tables (sessions, state, and events) to store session metadata, application state, and interaction events separately.

Implementation Details

In ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/agent.py, the implementation shows how to configure the service with a SQLite URL:

session_service = DatabaseSessionService(db_url="sqlite:///sessions.db")

The service automatically initializes the database schema on first run, creating:

  • sessions: Stores session IDs and metadata
  • state: Stores key-value application state as JSON
  • events: Stores the full event history including user and agent messages

Code Example

import asyncio
from google.adk.agents import LlmAgent
from google.adk.sessions import DatabaseSessionService
from google.adk.runners import Runner
from google.genai import types
from dotenv import load_dotenv

load_dotenv()  # Loads GOOGLE_API_KEY

# Initialize persistent SQLite storage

session_service = DatabaseSessionService(db_url="sqlite:///sessions.db")

# Create the agent

agent = LlmAgent(
    name="memory_agent",
    model="gemini-1.5-flash",
    description="Agent with persistent memory",
    instruction="You are a helpful assistant. Remember facts about the user."
)

# Runner connects agent to storage

runner = Runner(agent=agent, app_name="memory_demo", session_service=session_service)

async def chat(user_id: str, session_id: str, message: str) -> str:
    # Ensure session exists

    session = await session_service.get_session("memory_demo", user_id, session_id)
    if not session:
        session = await session_service.create_session(
            "memory_demo", user_id, session_id, state={"history": []}
        )
    
    # Create user message

    content = types.Content(role="user", parts=[types.Part(text=message)])
    
    # Run and capture final response

    async for event in runner.run_async(
        user_id=user_id, session_id=session_id, new_message=content
    ):
        if event.is_final_response():
            return event.content.parts[0].text if event.content else ""

async def main():
    await session_service.initialize()  # Creates tables if needed

    
    user = "alice"
    session = "session_001"
    
    # Conversation turns

    for msg in ["I love programming in Python", "What language do I love?"]:
        response = await chat(user, session, msg)
        print(f"User: {msg}")
        print(f"Agent: {response}\n")

if __name__ == "__main__":
    asyncio.run(main())

Key Architectural Differences

While both frameworks use SQLite for persistence, they differ in schema design and control granularity:

OpenAI Agents SDK (SQLiteSession)

  • Stores conversation history as a serialized message list in a simplified table structure
  • Provides automatic prompt stitching without manual state management
  • Supports both transient (in-memory) and persistent modes via the optional db_path parameter
  • Requires less boilerplate for basic conversational memory

Google ADK (DatabaseSessionService)

  • Separates storage into three distinct tables: sessions, state, and events
  • Allows storage of arbitrary application state beyond message history via JSON columns
  • Requires explicit session initialization and retrieval in application code
  • Provides granular control over event streaming and state manipulation for complex workflows

Choose OpenAI SDK for rapid prototyping and simple conversational agents where you only need message history. Choose Google ADK when you need to persist complex application state or require fine-grained control over the session lifecycle.

Summary

Frequently Asked Questions

How does SQLite conversation memory survive application restarts?

SQLite stores data in a local file on disk (e.g., sessions.db or chat_history.db). When you configure SQLiteSession with a db_path parameter in OpenAI SDK or DatabaseSessionService with db_url="sqlite:///..." in Google ADK, the frameworks write conversation history to this file. On restart, the same file path reconnects to the existing database, and the frameworks automatically load prior messages when you instantiate a session with the same session_id.

Can I use the same SQLite database for multiple agents or users?

Yes. Both frameworks support multi-tenancy through the session_id parameter. In OpenAI SDK, create distinct SQLiteSession instances with unique session IDs (e.g., user_123, user_456) while pointing to the same database file. In Google ADK, the DatabaseSessionService uses composite keys (app_name, user_id, session_id) to isolate conversations, allowing a single SQLite file to serve thousands of distinct user sessions without data collision.

What is the difference between in-memory and persistent SQLite sessions in the OpenAI SDK?

The OpenAI Agents SDK's SQLiteSession class supports both modes through the optional db_path parameter. When you omit db_path (e.g., SQLiteSession("temp_id")), the session stores history in an in-memory SQLite database that persists only for the process lifetime—ideal for testing or stateless deployments. When you provide a file path (e.g., SQLiteSession("user_123", "chat.db")), the SDK writes to a persistent file on disk, enabling conversation continuity across application restarts and system reboots.

How can I query or debug the conversation history stored in SQLite?

Both frameworks use standard SQLite schemas that you can inspect using any SQLite client (e.g., sqlite3 CLI, DB Browser for SQLite, or Python's sqlite3 module). In OpenAI SDK implementations, the SQLiteSession stores messages in a table structure that you can query directly to inspect the conversation history. In Google ADK, the DatabaseSessionService creates three explicit tables—sessions (metadata), state (JSON application state), and events (message history)—allowing you to run SQL queries like SELECT * FROM events WHERE session_id = 'user_123' ORDER BY timestamp to debug conversation flow or audit agent interactions.

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 →