Skip to content

Add SQLAlchemy session backend for conversation history management #1357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Aug 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions examples/basic/sqlalchemy_session_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import asyncio

from agents import Agent, Runner
from agents.extensions.memory.sqlalchemy_session import SQLAlchemySession


async def main():
# Create an agent
agent = Agent(
name="Assistant",
instructions="Reply very concisely.",
)

# Create a session instance with a session ID.
# This example uses an in-memory SQLite database.
# The `create_tables=True` flag is useful for development and testing.
session = SQLAlchemySession.from_url(
"conversation_123",
url="sqlite+aiosqlite:///:memory:",
create_tables=True,
)

print("=== SQLAlchemySession Example ===")
print("The agent will remember previous messages automatically.\n")

# First turn
print("User: What city is the Golden Gate Bridge in?")
result = await Runner.run(
agent,
"What city is the Golden Gate Bridge in?",
session=session,
)
print(f"Assistant: {result.final_output}\n")

# Second turn - the agent will remember the previous conversation
print("User: What state is it in?")
result = await Runner.run(
agent,
"What state is it in?",
session=session,
)
print(f"Assistant: {result.final_output}\n")

print("=== Conversation Complete ===")


if __name__ == "__main__":
# To run this example, you need to install the sqlalchemy extras:
# pip install "agents[sqlalchemy]"
asyncio.run(main())
3 changes: 2 additions & 1 deletion examples/realtime/app/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import logging
import struct
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING, Any, assert_never
from typing import TYPE_CHECKING, Any

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from typing_extensions import assert_never

from agents.realtime import RealtimeRunner, RealtimeSession, RealtimeSessionEvent

Expand Down
2 changes: 1 addition & 1 deletion examples/realtime/cli/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self) -> None:
# Audio output state for callback system
self.output_queue: queue.Queue[Any] = queue.Queue(maxsize=10) # Buffer more chunks
self.interrupt_event = threading.Event()
self.current_audio_chunk: np.ndarray | None = None # type: ignore
self.current_audio_chunk: np.ndarray[Any, np.dtype[Any]] | None = None
self.chunk_position = 0

def _output_callback(self, outdata, frames: int, time, status) -> None:
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ voice = ["numpy>=2.2.0, <3; python_version>='3.10'", "websockets>=15.0, <16"]
viz = ["graphviz>=0.17"]
litellm = ["litellm>=1.67.4.post1, <2"]
realtime = ["websockets>=15.0, <16"]
sqlalchemy = ["SQLAlchemy>=2.0", "asyncpg>=0.29.0"]

[dependency-groups]
dev = [
Expand All @@ -63,6 +64,7 @@ dev = [
"mkdocs-static-i18n>=1.3.0",
"eval-type-backport>=0.2.2",
"fastapi >= 0.110.0, <1",
"aiosqlite>=0.21.0",
]

[tool.uv.workspace]
Expand Down
15 changes: 15 additions & 0 deletions src/agents/extensions/memory/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

"""Session memory backends living in the extensions namespace.
This package contains optional, production-grade session implementations that
introduce extra third-party dependencies (database drivers, ORMs, etc.). They
conform to the :class:`agents.memory.session.Session` protocol so they can be
used as a drop-in replacement for :class:`agents.memory.session.SQLiteSession`.
"""
from __future__ import annotations

from .sqlalchemy_session import SQLAlchemySession # noqa: F401

__all__: list[str] = [
"SQLAlchemySession",
]
Loading