SQLAlchemySession on PostgreSQL returns items out of order and pops the wrong item when created_at is not monotonic
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 85/100
Direzione di ricerca
Inizia in src/agents/extensions/memory/sqlalchemy_session.py, dove get_items e pop_item ordinano per created_at, id. Leggi la definizione di Column per created_at e le chiamate order_by sia nei metodi sincroni sia in quelli asincroni. Cambia l'ordinamento impostando solo id oppure salva i timestamp come UTC, poi esegui lo script di riproduzione dell'issue per confermare che i turni vengono restituiti nell'ordine di aggiunta. Fatto significa che get_items e pop_item corrispondono al comportamento di SQLiteSession.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Please read this first
- Have you read the docs? Agents SDK docs
Yes - Have you searched for related issues? Others may have faced similar issues.
Yes. #1900 fixed ties between equal timestamps by addingidas a tie-breaker. This report is about timestamps that go backwards.
Describe the bug
Currently, SQLAlchemySession.get_items and pop_item order rows by created_at first and id second. The column is TIMESTAMP(timezone=False) with server_default=CURRENT_TIMESTAMP. On PostgreSQL that value is the transaction start time, converted to the wall clock of the connection's TimeZone setting. It does not follow the order in which rows were appended:
- writers whose connections use different
TimeZonesettings write timestamps that differ by the UTC offset; - on a server whose time zone observes daylight saving time, the wall clock repeats an hour when the clocks fall back, so rows written during the repeated hour can sort before rows written in the hour just before it.
In each case get_items() returns turns out of order, get_items(limit=1) returns an item that is not the latest, and pop_item() deletes and returns an item that is not the most recent. #1900 shows what such a reordering does to the next run: a reasoning item that sorts after its message makes the Responses API reject the input with Item 'msg_...' of type 'message' was provided without its required 'reasoning' item. SQLiteSession and AsyncSQLiteSession order by id and return the append order for the same calls. The Session docstrings say get_items returns items "in chronological order" and pop_item removes "the most recent item".
The same ordering is on main (src/agents/extensions/memory/sqlalchemy_session.py):
Column(
"created_at",
TIMESTAMP(timezone=False),
server_default=sql_text("CURRENT_TIMESTAMP"),
nullable=False,
),
.order_by(
self._messages.c.created_at.desc(),
self._messages.c.id.desc(),
)
Debug information
- Agents SDK version: 0.24.0
- Related library versions (optional, e.g.
any-llm,litellm, orpydantic): SQLAlchemy 2.1.6, asyncpg 0.32.0, PostgreSQL 17.11 - Python version: 3.12.13
- Operating system: macOS 26.6.2, arm64 (Darwin 25.6.0)
- Model and model provider: none (session API only)
- Does the issue reproduce with the latest Agents SDK release? Yes, 0.24.0; main has the same code.
- Does the issue occur consistently or intermittently? Consistently with the script below.
Repro steps
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine
from agents.extensions.memory import SQLAlchemySession
URL = "postgresql+asyncpg://postgres@localhost:5432/postgres"
async def main():
# two app instances whose connections use different TimeZone settings
utc = create_async_engine(URL, connect_args={"server_settings": {"timezone": "UTC"}})
toronto = create_async_engine(URL, connect_args={"server_settings": {"timezone": "America/Toronto"}})
a = SQLAlchemySession("conv", engine=utc, create_tables=True)
b = SQLAlchemySession("conv", engine=toronto, create_tables=True)
await a.clear_session()
await a.add_items([{"role": "user", "content": "turn 1"}])
await a.add_items([{"role": "user", "content": "turn 2"}])
await b.add_items([{"role": "user", "content": "turn 3"}])
print([i["content"] for i in await a.get_items()])
# actual: ['turn 3', 'turn 1', 'turn 2']
# expected: ['turn 1', 'turn 2', 'turn 3']
print([i["content"] for i in await a.get_items(limit=1)])
# actual: ['turn 2']
# expected: ['turn 3']
print((await a.pop_item())["content"])
# actual: turn 2
# expected: turn 3
asyncio.run(main())
With both engines set to the same TimeZone, the output is the expected one. A server whose own time zone observes daylight saving time behaves like the second engine after the clocks fall back. With TimeZone set to America/Toronto, SELECT '2026-11-01 05:59:00+00'::TIMESTAMPTZ::TIMESTAMP, '2026-11-01 06:00:00+00'::TIMESTAMPTZ::TIMESTAMP returns 2026-11-01 01:59:00 and 2026-11-01 01:00:00: a row written one minute later gets a created_at 59 minutes earlier.
Expected behavior
get_items returns items in the order they were added, and pop_item removes the last item added, as SQLiteSession does for the same calls. Storing created_at as TIMESTAMP WITH TIME ZONE (or always in UTC) keeps the current created_at, id ordering correct; ordering by id alone also gives that order.
- Lingua principale
- Python
- Stelle
- 30.4k
- Fork
- 4.9k
- Merge medio
- 19h 5m
- PR unite (30g)
- 90
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di openai/openai-agents-python
-
Docs: `tool_choice="required"` can select a state-changing tool when the needed one is not shownAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
openai/openai-agents-python#5461 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
openai/openai-agents-python#5460 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
openai/openai-agents-python#5458 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
openai/openai-agents-python#5455 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
openai/openai-agents-python#5451 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di openai/openai-agents-python
Issue simili
-
URLValidator ignores an explicit empty scheme allowlistForse già presa @IlyaKhalafi l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
tortoise/tortoise-orm#2393 ·
I maintainer di solito rispondono entro 2 giorni
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
frappe/frappe_docker#2046 ·
I maintainer di solito rispondono entro 1 giorno
-
Weekly link check failedAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
-
complete_box_iou_loss / complete_box_iou: NaN gradients for zero-height boxes, NaN for point boxesAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
AXI SMU SPEC
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
tenstorrent/tt-oca-harness#3556 ·
I maintainer di solito rispondono entro 1 giorno