Skip to content

feat: #2072 pass RunContextWrapper to Session get_items/add_items#3591

Open
jawwad-ali wants to merge 4 commits into
openai:mainfrom
jawwad-ali:feat/2072-session-context-wrapper
Open

feat: #2072 pass RunContextWrapper to Session get_items/add_items#3591
jawwad-ali wants to merge 4 commits into
openai:mainfrom
jawwad-ali:feat/2072-session-context-wrapper

Conversation

@jawwad-ali

Copy link
Copy Markdown
Contributor

Summary

Sessions can now opt into receiving the current run's RunContextWrapper[T] by accepting a keyword-only wrapper parameter on get_items/add_items, so a custom session can manage conversation history and run context together (per-user storage scoping, context-derived metadata, etc.).

Design points:

  • Zero breaking changes for existing sessions. The runner checks the session's method signature (session_method_accepts_wrapper, following the existing is_openai_responses_compaction_aware_session capability pattern) and only forwards the wrapper to implementations that accept it. Sessions with pre-existing signatures never receive the kwarg — covered by dedicated regression tests.
  • Keyword-only, placed last, consistent everywhere (per the review feedback on feat: propagate RunContextWrapper to session history read/write paths #2690): the parameter is *, wrapper: RunContextWrapper[Any] | None = None across the Session protocol, SessionABC, all 10 built-in implementations, and examples/memory/file_session.py.
  • Wrapper-style sessions forward it. EncryptedSession and OpenAIResponsesCompactionSession pass the wrapper through to opted-in underlying sessions (and never to legacy ones).
  • The wrapper is threaded through every runner-driven session read/write: input preparation (including the session_input_callback merge path and SessionSettings limits), turn persistence for run/run_sync/run_streamed, resumed-turn persistence, and guardrail-trip input persistence.

This revives #2690 by @HuxleyHu98, which had addressed the review feedback before timing/staleness closed it. The implementation here incorporates that review feedback, is rebased onto the current run_internal layout, and extends coverage to MongoDBSession (added since), the guardrail-trip persistence path, and a larger test suite.

Test plan

  • New tests/memory/test_session_context_wrapper.py with 26 tests: wrapper delivery and wrapper.context identity across Runner.run / run_sync / run_streamed; legacy-session (old signature) backward compatibility through the runner; **kwargs-style sessions; the session_input_callback merge path; the SessionSettings(limit=...) path; guardrail-trip input persistence; EncryptedSession and OpenAIResponsesCompactionSession forwarding (including legacy underlying sessions); a signature audit asserting every built-in session exposes the keyword-only parameter; and unit tests for the capability check.
  • Existing fake sessions in the test suite were updated to the new signature; mock-based call assertions now expect the forwarded kwarg.
  • make format, make lint pass; make typecheck (mypy + pyright) reports no new errors relative to main (verified by diffing full mypy output against a clean main worktree); full test suite run locally with only pre-existing environment-related failures that reproduce identically on clean main.

Issue number

Closes #2072

Notes

  • Scope intentionally matches feat: propagate RunContextWrapper to session history read/write paths #2690: only get_items/add_items receive the wrapper (the runner-driven history read/write paths). pop_item/clear_session and internal rewind/compaction-maintenance reads keep their current signatures and behavior.
  • Static-typing note: third-party sessions subclassing SessionABC with the old signatures will see mypy/pyright [override] hints until they add the optional kwarg; runtime behavior is unchanged either way. Sessions implementing the Session protocol structurally are unaffected at runtime; the runner treats them as not opted in.
  • docs/sessions/index.md gains a short "Accessing the run context in custom sessions" section (English only; translated docs are generated).

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

Sessions can now opt into receiving the current run's
RunContextWrapper by accepting a keyword-only wrapper parameter on
get_items/add_items. The runner inspects the session's signature and
only forwards the wrapper to implementations that accept it, so
existing custom sessions keep working unchanged. Wrapper-style
sessions (EncryptedSession, OpenAIResponsesCompactionSession) forward
the wrapper to opted-in underlying sessions.

This revives the approach from openai#2690, which addressed maintainer
review feedback before going stale, rebased onto the current runner
internals and extended to MongoDBSession and the guardrail-trip
persistence path.

Closes openai#2072

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

Copy link
Copy Markdown

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: cdf4f0317f

ℹ️ 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/run_internal/run_loop.py
Comment thread src/agents/memory/openai_responses_compaction_session.py Outdated
@seratch seratch added duplicate This issue or pull request already exists feature:sessions labels Jun 7, 2026
…action paths

Addresses review feedback: a wrapper-aware session that scopes storage
by wrapper.context was getting the wrapper on normal reads/writes but
not on the conversation-retry rewind path or the compaction decorator's
internal history reads/replacements, so those operated on the
unscoped/default store.

- Thread the wrapper through rewind_session_items, the tail-suffix
  rewind, cleanup verification, and popped-item restoration.
- Thread the wrapper through OpenAIResponsesCompactionSession's
  run_compaction, candidate loading, and replace/restore helpers, and
  add it to the run_compaction protocol method.

clear_session/pop_item keep their existing signatures, matching the
get_items/add_items-only scope of this change.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review


P2 Badge Pass the wrapper to retry pops

Fresh evidence after the update is that the tail is now read with wrapper above, but the actual removal still calls the wrapperless pop_item(). For a session that scopes storage by wrapper.context as the new docs describe, a transient model/stream retry can verify the scoped tail and then pop from the unscoped/default backing store, leaving the just-persisted scoped input in place so the retry appends it again. The pop path needs the same context as the read/write path, or wrapper-scoped sessions cannot be used safely with retry rewind.

ℹ️ 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/memory/openai_responses_compaction_session.py
…tionSession

The compaction decorator rewrites history by clearing and replacing the
underlying store during compaction. clear_session is intentionally not
part of the get_items/add_items wrapper contract, so scoping only the
reads and adds (but not the clear) would let compaction read/write a
context-scoped store while clearing the default scope.

Make the decorator consistent instead: it accepts the keyword-only
wrapper to stay protocol-compatible but does not forward it to the
underlying session, so all of its history operations use the same
(default) scope. Document that wrapping a context-scoped session in the
compaction decorator is unsupported for run-context scoping, while
transparent proxies like EncryptedSession still forward the wrapper.

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

Copy link
Copy Markdown

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: 327ab24cdc

ℹ️ 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/run_internal/session_persistence.py Outdated
The retry-rewind path removes items via pop_item, which is outside the
get_items/add_items run-context wrapper contract. Scoping only the tail
reads (but not the pop) would let a wrapper-scoped session verify the
scoped tail and then pop from the default scope, leaving the scoped
items in place. Keep the rewind path unscoped so its reads and pops use
the same (default) scope, mirroring the OpenAIResponsesCompactionSession
decision. Documented that retry rewind and compaction run against the
default scope for wrapper-scoped sessions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists feature:sessions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pass RunContextWrapper[T] to Session methods

2 participants