Skip to content

feat(extensions): add MongoDB session backend#2902

Open
alexbevi wants to merge 7 commits intoopenai:mainfrom
alexbevi:mongodb-memory
Open

feat(extensions): add MongoDB session backend#2902
alexbevi wants to merge 7 commits intoopenai:mainfrom
alexbevi:mongodb-memory

Conversation

@alexbevi
Copy link
Copy Markdown

@alexbevi alexbevi commented Apr 15, 2026

Summary

Adds MongoDBSession to src/agents/extensions/memory/, a MongoDB-backed session store. I followed the extensions/memory directory structure established in #1328 as this was suggested as a path forward on the previous (now closed) PR #1364.

Notes:

  • Two-collection schema: agent_sessions (metadata) + agent_messages (individual conversation items), with a compound index on (session_id, _id) for efficient per-session chronological queries.
  • Index creation is idempotent — one-shot per (id(client), database, sessions_collection, messages_collection) key, guarded by a per-key asyncio.Lock. The client identity is included so that different AsyncMongoClient instances (e.g. pointing at different clusters) each get their own init pass.
  • from_uri() factory owns the client lifecycle; injected clients are left unmanaged (caller's responsibility).
  • Supports SessionSettings.limit and explicit per-call limit overrides, consistent with all other session backends.
  • Corrupted or malformed documents are silently skipped rather than raising.

Install: pip install openai-agents[mongodb]

Issue number

Relates to #1364, #1328

Checks

  • I've added new tests (if relevant)
  • I've added/updated the relevant documentation
  • I've run make lint and make format
  • I've made sure tests pass

alexbevi and others added 3 commits April 15, 2026 16:08
Implements MongoDBSession under src/agents/extensions/memory/ following
the extensions directory structure established in issue openai#1328. Uses
pymongo>=4.13's native AsyncMongoClient (pymongo.asynchronous) rather
than Motor.

- Two-collection schema: agent_sessions (metadata) + agent_messages (items)
- Chronological ordering via ObjectId; compound index on (session_id, _id)
- Idempotent one-shot index creation with per-key asyncio.Lock
- from_uri() factory with owned-client lifecycle tracking
- Supports SessionSettings.limit and explicit per-call limit overrides
- Gracefully skips corrupted/missing message_data documents
- ping() / close() lifecycle helpers; close() only touches owned clients

Adds 26 tests in tests/extensions/memory/test_mongodb_session.py using
in-process fake pymongo types injected via sys.modules — no real MongoDB
or pymongo installation required to run the suite.

Install: pip install openai-agents[mongodb]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements both client metadata patterns per the add-client-metadata skill:

- Pattern A (from_uri): passes driver=_DRIVER_INFO to AsyncMongoClient via
  client_kwargs.setdefault(), so caller-supplied driver values are preserved.
- Pattern B (injected client): calls client.append_metadata(_DRIVER_INFO) in
  __init__ guarded by hasattr, compatible with PyMongo <4.14.

_DRIVER_INFO is a module-level DriverInfo(name="openai-agents", version=...)
where version is resolved at runtime via importlib.metadata.

Adds three new tests covering both patterns and the no-overwrite guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@alexbevi alexbevi changed the title add MongoDBSession extension feat(extensions): add MongoDB session backend Apr 15, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c2a083d9f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
- P1: Use client.close() (sync) instead of aclose() when closing an
  owned AsyncMongoClient; PyMongo does not expose aclose().
- P1: Include id(client) in _init_key so that different AsyncMongoClient
  instances pointing at different clusters each run their own index-
  creation pass rather than sharing a single guard.
- P2: Add TypeError to the except tuple in get_items() and pop_item() so
  non-string BSON message_data values (e.g. int/object) are silently
  skipped rather than aborting history retrieval.

Adds two new tests: test_non_string_message_data_is_skipped (P2) and
test_different_clients_each_run_index_init (P1).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the enhancement New feature or request label Apr 15, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 436289f769

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
With pymongo now installed in dev deps, mypy resolves the real async
types so several ignore codes were wrong or unused:
- Make FakeAsyncMongoClient.close() async (MongoDBSession awaits it)
- Change method-assignment ignores from [attr-defined] to [method-assign]
- Add [assignment] to admin.command monkey-patch (overloaded function)
- Remove ignores on _docs access and create_index reads that mypy now
  handles via the Any type parameter on AsyncCollection[Any]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 054d391340

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
- Replace asyncio.Lock process-wide guard with threading.Lock so
  _get_or_create_init_lock() is safe to call from any event loop
- Replace id(client)-keyed dicts with WeakKeyDictionary so entries are
  pruned when clients are GC'd, preventing stale id reuse from skipping
  index creation on a new client
- Add explicit seq field (monotonic per-session counter via $inc) to
  every message document and sort by seq instead of _id; ObjectId is
  only second-level accurate across processes and not reliably monotonic
- Update FakeAsyncCollection in tests with find_one_and_update + $inc
  support; replace _initialized_keys/_init_locks clears with _init_state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b166de716

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/extensions/memory/mongodb_session.py Outdated
@alexbevi alexbevi marked this pull request as draft April 15, 2026 21:36
…only guard

The per-entry asyncio.Lock stored in _init_state was still loop-bound:
a second event loop reusing the same AsyncMongoClient would hang or
raise RuntimeError trying to acquire it.

create_index is idempotent on the server side, so no async coordination
is needed — concurrent first-time callers may each issue a redundant
create_index round-trip, but that is harmless. Replace the asyncio.Lock
with a plain bool guarded by the existing threading.Lock, removing the
last asyncio.Lock from the process-wide registry entirely.

Also removes the now-unused asyncio import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@alexbevi alexbevi marked this pull request as ready for review April 16, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant