Skip to content

feat(memory): add runtime-gated conversation memory substrate - #1149

Merged
slin1237 merged 8 commits into
mainfrom
feat/conversation-memory-substrate
Apr 22, 2026
Merged

slin1237 merged 8 commits into
mainfrom
feat/conversation-memory-substrate

Conversation

@zhoug9127

@zhoug9127 zhoug9127 commented Apr 15, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Problem

SMG needed safe, runtime-gated memory substrate plumbing so memory intent can be parsed from request headers and carried through request handling without changing existing behavior.
We also needed startup-time guardrails to fail fast on invalid runtime/backend/hook combinations instead of failing later during execution.

Solution

This PR adds memory substrate plumbing behind a runtime gate (memory_runtime.enabled, default false) and keeps default behavior unchanged.

  • Added MemoryRuntimeConfig on RouterConfig (enabled: bool, default off).
  • Added a new memory module with MemoryExecutionContext and execution state modeling:
    • NotRequested
    • GatedOff
    • Active
  • Added memory header parsing/normalization from x-conversation-memory-config (JSON), including:
    • long_term_memory.enabled
    • long_term_memory.policy
    • long_term_memory.subject_id
    • long_term_memory.embedding_model_id
    • long_term_memory.extraction_model_id
    • (also parsed for future use: short_term_memory.*)
  • Added policy parsing for store_only, store_and_recall, recall_only, and none with safe fallback for unrecognized values.
  • Added request-context wiring so memory execution context is built from headers and threaded through OpenAI/Responses handling and storage handles.
  • Storage plumbing updates:
    • create_storage now returns StorageBundle (instead of tuple), including conversation_memory_writer.
    • HistoryBackend::Memory provides MemoryConversationMemoryWriter.
    • Other backends provide NoOpConversationMemoryWriter.
  • Added startup/runtime validation in AppContextBuilder to reject unsupported combinations:
    • memory_runtime.enabled=true with backends that do not provide a real memory writer.
    • memory_runtime.enabled=true with storage_hook_wasm_path (currently unsupported).
  • Conversations ingestion prep:
    • Added create_conversation_items_with_headers(...) and server wiring to pass MemoryExecutionContext (reserved for follow-up ingestion logic).

Scope Notes

  • No user-facing enablement path yet (no CLI flag / Python binding / config-file rollout path). This is intentional for staged rollout.
  • No behavior change for default configs (memory_runtime.enabled=false).
  • Responses memory injection remains intentionally no-op in this PR (hook/wiring only).

Changes by Area

  • data-connector
    • Added StorageBundle and backend_supports_memory_writer(...).
    • Added conversation_memory_writer through storage factory outputs.
    • Added in-memory MemoryConversationMemoryWriter for HistoryBackend::Memory.
    • Added/used NoOpConversationMemoryWriter for non-memory backends.
    • Updated exports/tests accordingly.
  • model_gateway
    • Added memory module (MemoryExecutionContext).
    • Added memory config header parsing utilities in header_utils.
    • Threaded memory execution context + conversation memory writer through app/openai/grpc/storage context.
    • Added startup validation helper in AppContextBuilder.
    • Added header-aware conversations create-items entrypoint and server wiring for future memory-aware ingestion.

Test Plan

Reproducible validation run locally:

pre-commit run --all-files
cargo check -p smg -p data-connector
cargo test -p smg memory::context -- --nocapture
cargo test -p data-connector factory::tests -- --nocapture

Results:

  • All commands above passed.
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Summary by CodeRabbit

  • New Features
    • Conversation memory management with configurable runtime enable/disable.
    • Per-request memory policies and optional overrides (subject ID, embedding model, extraction model) via headers.
    • In-memory conversation memory storage and writer support.
    • Runtime validation to ensure memory runtime and storage backend compatibility.
    • Memory execution context propagated into request handling for memory-aware processing.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Apr 15, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors storage factory to return a StorageBundle including an optional ConversationMemoryWriter, implements an in‑memory MemoryConversationMemoryWriter, adds memory runtime config and header parsing, introduces MemoryExecutionContext derived from headers+config, and threads memory writer/context through app components, middleware, and handlers.

Changes

Cohort / File(s) Summary
Data Connector - Storage & Memory Writer
crates/data_connector/src/factory.rs, crates/data_connector/src/memory.rs, crates/data_connector/src/lib.rs
Replaced storage tuple with StorageBundle (adds conversation_memory_writer: Option<Arc<dyn ConversationMemoryWriter>>); return Some writer only for HistoryBackend::Memory; added MemoryConversationMemoryWriter implementation and tests; exported StorageBundle and backend_supports_memory_writer.
AppContext & Storage Threading
model_gateway/src/app_context.rs, model_gateway/src/service_discovery.rs
Added conversation_memory_writer: Option<Arc<dyn ConversationMemoryWriter>> to AppContext and builder; validate memory-writer/config combinations; test context initialization sets writer field.
Router / Request Context Wiring
model_gateway/src/routers/openai/context.rs, model_gateway/src/routers/openai/router.rs, model_gateway/src/routers/conversations/handlers.rs, model_gateway/src/server.rs
Threaded conversation_memory_writer and memory_execution_context into router/component structs and request contexts; added create_conversation_items_with_headers and updated server route to build and pass MemoryExecutionContext from headers.
Memory Runtime Config & Builder
model_gateway/src/config/types.rs, model_gateway/src/config/builder.rs
Added MemoryRuntimeConfig { enabled: bool }, defaulted into RouterConfig, and fluent builder setter memory_runtime_config().
Memory Execution Context Module
model_gateway/src/memory/context.rs, model_gateway/src/memory/mod.rs, model_gateway/src/lib.rs
New MemoryExecutionContext, MemoryExecutionState, and MemoryPolicyMode with header-driven parsing, runtime gating, model overrides, and unit tests; exported via model_gateway::memory.
Header Parsing Utilities
model_gateway/src/routers/common/header_utils.rs
Added header constants and MemoryHeaderView::from_http_headers with trimming/blank handling for policy, subject-id, embedding-model, extraction-model; new tests.
Middleware & Helpers
model_gateway/src/middleware/storage_context.rs, model_gateway/src/middleware/mod.rs, model_gateway/src/config/validation.rs
Added build_memory_execution_context(config, headers) helper (crate-visible re-export); minor formatting change in validator.

Sequence Diagram

sequenceDiagram
    participant Client as HTTP Request
    participant Server as Route Handler
    participant Middleware as Storage Middleware
    participant MemoryCtx as MemoryExecutionContext
    participant App as AppContext
    participant Writer as ConversationMemoryWriter

    Client->>Server: request + headers
    Server->>Middleware: pass HeaderMap
    Middleware->>MemoryCtx: build_memory_execution_context(config, headers)
    MemoryCtx->>MemoryCtx: parse policy header (trim, ci)
    MemoryCtx->>MemoryCtx: determine store/recall state (Active/GatedOff/NotRequested)
    Middleware-->>Server: MemoryExecutionContext
    Server->>App: access AppContext (includes optional writer)
    App-->>Server: conversation_memory_writer (Option)
    Server->>Server: process items with memory context and optional writer
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • CatherineSue
  • key4ng

🐰
I found a header, trimmed and neat,
I parse its policy, swift of feet,
If runtime says the memory's on,
I hop and store each memory drawn,
A tiny writer, safe and sweet.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature being introduced: a runtime-gated memory substrate for conversation memory functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/conversation-memory-substrate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added data-connector Data connector crate changes model-gateway Model gateway crate changes openai OpenAI router changes labels Apr 15, 2026
Comment thread model_gateway/src/memory/context.rs Outdated
Comment thread crates/data_connector/src/memory.rs Outdated
Comment thread model_gateway/src/routers/openai/context.rs

@claude claude 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.

Clean scaffolding PR that threads memory plumbing through the system with proper runtime gating. The StorageTuple → StorageBundle upgrade, validation in AppContextBuilder, and header-driven MemoryExecutionContext are all well-structured.

Summary: 0 🔴 Important · 3 🟡 Nit · 0 🟣 Pre-existing

Nits:

  • Split impl Policy blocks in memory/context.rs — consolidate into one
  • Doc comment after #[derive] in memory.rs — move before derives per convention
  • refresh_memory_execution_context is pub with no callers — consider annotating as scaffolding

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@model_gateway/src/routers/conversations/handlers.rs`:
- Around line 328-331: The code constructs a MemoryExecutionContext via
middleware::build_memory_execution_context but immediately drops it, so
header-derived memory headers are ignored; modify the call sites so the returned
MemoryExecutionContext is threaded into the downstream ingestion flow (e.g.,
pass it into create_conversation_items_with_headers or attach it to the
request/context object that is handed to the ingestion pipeline) and persist or
clone it as needed so create_conversation_items_with_headers can read and act on
the x-smg-ltm-memory-* headers; ensure all places that call
middleware::build_memory_execution_context (and the
create_conversation_items_with_headers signature) are updated to accept and
propagate the MemoryExecutionContext.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bcf16ed0-a079-439a-9e92-271028d57a24

📥 Commits

Reviewing files that changed from the base of the PR and between e85af89 and b5cb7d6.

📒 Files selected for processing (18)
  • crates/data_connector/src/factory.rs
  • crates/data_connector/src/lib.rs
  • crates/data_connector/src/memory.rs
  • crates/data_connector/src/noop.rs
  • model_gateway/src/app_context.rs
  • model_gateway/src/config/builder.rs
  • model_gateway/src/config/types.rs
  • model_gateway/src/config/validation.rs
  • model_gateway/src/lib.rs
  • model_gateway/src/memory/context.rs
  • model_gateway/src/memory/mod.rs
  • model_gateway/src/middleware.rs
  • model_gateway/src/routers/common/header_utils.rs
  • model_gateway/src/routers/conversations/handlers.rs
  • model_gateway/src/routers/openai/context.rs
  • model_gateway/src/routers/openai/router.rs
  • model_gateway/src/server.rs
  • model_gateway/src/service_discovery.rs
💤 Files with no reviewable changes (1)
  • model_gateway/src/config/validation.rs

Comment thread model_gateway/src/routers/conversations/handlers.rs Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
model_gateway/src/routers/conversations/handlers.rs (1)

319-325: ⚠️ Potential issue | 🟠 Major

Header-derived memory context is still a no-op here.

Line 403 makes MemoryExecutionContext intentionally unused, so /v1/conversations/{conversation_id}/items still ignores the new x-smg-ltm-memory-* headers. Either trigger the memory store/recall behavior from this ingestion path, or defer the header-aware API until the context actually affects processing.

Also applies to: 350-357, 398-404

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/conversations/handlers.rs` around lines 319 - 325,
The handler create_conversation_items_with_headers accepts a
MemoryExecutionContext but currently ignores it (marked unused) so the
x-smg-ltm-memory-* headers have no effect; update the ingestion path to apply
the memory context by invoking the existing memory recall/store APIs inside
create_conversation_items_with_headers (and the related handlers referenced
around the same area) before persisting items: extract the relevant flags/fields
from MemoryExecutionContext, call the memory recall function to retrieve any
preloaded memory to include in item processing, and after item creation call the
memory store function when the context indicates storing is required, making
sure to use the MemoryExecutionContext type and existing memory store/recall
method names to tie header-derived behavior to the item ingestion flow rather
than leaving the parameter unused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/data_connector/src/memory.rs`:
- Around line 282-307: Add a unit test that verifies the happy path for
MemoryConversationMemoryWriter: construct a MemoryConversationMemoryWriter, call
create_memory with a minimal NewConversationMemory, assert the returned
ConversationMemoryId starts with "mem_" and that the writer's inner store
contains the inserted NewConversationMemory under that id (access inner via
MemoryConversationMemoryWriter.inner read lock). Use the create_memory async
method (await it) and check cloning/lookup via id.clone(); reference
MemoryConversationMemoryWriter, create_memory, ConversationMemoryId,
NewConversationMemory, and inner in the test.

---

Duplicate comments:
In `@model_gateway/src/routers/conversations/handlers.rs`:
- Around line 319-325: The handler create_conversation_items_with_headers
accepts a MemoryExecutionContext but currently ignores it (marked unused) so the
x-smg-ltm-memory-* headers have no effect; update the ingestion path to apply
the memory context by invoking the existing memory recall/store APIs inside
create_conversation_items_with_headers (and the related handlers referenced
around the same area) before persisting items: extract the relevant flags/fields
from MemoryExecutionContext, call the memory recall function to retrieve any
preloaded memory to include in item processing, and after item creation call the
memory store function when the context indicates storing is required, making
sure to use the MemoryExecutionContext type and existing memory store/recall
method names to tie header-derived behavior to the item ingestion flow rather
than leaving the parameter unused.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e32d1935-0e66-471b-9d3a-f2146e3c4e8b

📥 Commits

Reviewing files that changed from the base of the PR and between b5cb7d6 and 33b2032.

📒 Files selected for processing (5)
  • crates/data_connector/src/memory.rs
  • model_gateway/src/memory/context.rs
  • model_gateway/src/routers/conversations/handlers.rs
  • model_gateway/src/routers/openai/context.rs
  • model_gateway/src/server.rs

Comment thread crates/data_connector/src/memory.rs
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from 56a9503 to 7b6bc6a Compare April 15, 2026 08:26
Comment thread model_gateway/src/app_context.rs Outdated
Comment thread model_gateway/src/routers/conversations/handlers.rs
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from 7b6bc6a to a0e48e7 Compare April 15, 2026 08:46
Comment thread model_gateway/src/memory/context.rs
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from a0e48e7 to 7926d37 Compare April 15, 2026 16:01
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from 7926d37 to 6768b71 Compare April 15, 2026 16:04

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/data_connector/src/factory.rs`:
- Around line 249-254: Update the factory tests that call create_storage and
unpack the StorageBundle (where they currently destructure
bundle.response_storage, bundle.conversation_storage,
bundle.conversation_item_storage) to also assert the new
conversation_memory_writer contract: verify that when HistoryBackend::Memory is
configured the returned bundle.conversation_memory_writer is Some(writer) and
when HistoryBackend::None is configured the field is None (to enforce the
startup precheck), and ensure any hook-wrapped bundles preserve that writer
presence/absence rather than dropping or populating it incorrectly.

In `@model_gateway/src/memory/context.rs`:
- Around line 25-31: The code currently warns when headers.policy is present but
unrecognized even if it is blank/whitespace; update the logic around
headers.policy and Policy::Unspecified so that you first trim raw_policy (e.g.,
let trimmed = raw_policy.trim()) and if trimmed.is_empty() treat it as
unspecified with no warn!, and only call warn! when trimmed is non-empty and the
parsed policy still matched Policy::Unspecified; ensure you continue to pass the
original raw value (or the trimmed value) into the log for context when warning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d1f08e88-d128-4ec6-8061-b99644e5f83b

📥 Commits

Reviewing files that changed from the base of the PR and between 33b2032 and 7926d37.

📒 Files selected for processing (6)
  • crates/data_connector/src/factory.rs
  • crates/data_connector/src/lib.rs
  • crates/data_connector/src/memory.rs
  • model_gateway/src/app_context.rs
  • model_gateway/src/memory/context.rs
  • model_gateway/src/routers/conversations/handlers.rs

Comment thread crates/data_connector/src/factory.rs
Comment thread model_gateway/src/memory/context.rs Outdated

@slin1237 slin1237 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for putting this together, Daisy! The shape of the design (header → context → request pipeline → storage handle) is solid, and the StorageTuple → StorageBundle refactor is a nice cleanup.

Left a few small inline suggestions focused on type design and consistency with patterns the codebase already uses — none are blockers, just foundation tightening that's cheaper to do now than after consumer code lands. The MemoryExecutionContext enum suggestion is probably the highest-leverage one.

One bigger-picture note that's worth a sentence in the PR description: the memory_runtime flag has no user-facing way to be enabled today (no CLI flag, no Python binding, no config-file path). If staged rollout is intentional, calling that out would help reviewers calibrate. If not, wiring the CLI flag here would close the loop.

+1 to CodeRabbit's still-open observation about _memory_execution_context being unused at handlers.rs:402 — happy to defer until the consumer lands, but a // TODO(memory): wire into ingestion comment would keep it from getting lost.

Great scaffolding work, looking forward to seeing the consumer wire up!

pub subject_id: Option<String>,
pub embedding_model: Option<String>,
pub extraction_model: Option<String>,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice job gating store/recall through here. One small refactor that would tighten the type: the (requested, active) pairs encode 4 representable states but only 3 are valid — (requested=false, active=true) is impossible, but the type allows it because all fields are pub.

An enum like LtmStoreState::{NotRequested, GatedOff, Active} would let the type system enforce what your constructor enforces today, and would let downstream consumers match on intent instead of remembering to read _active (not _requested) at the right spot. Small thing, but it'll prevent a future correctness bug as the consumer lands.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks! I followed the pattern LtmStoreState::{NotRequested, GatedOff, Active} and replaced the old pairs.

Please check: model_gateway/src/memory/context.rs line 14 with latest commit.

Comment thread model_gateway/src/memory/context.rs Outdated

fn disables_ltm(self) -> bool {
matches!(self, Self::None)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Small observation: Policy::None and Policy::Unspecified produce identical (store_requested=false, recall_requested=false) results in the constructor above, so disables_ltm() and the else branch are currently equivalent. Either collapse the two variants, or make None observably different (e.g. a tracing::info! on explicit opt-out, or surfacing it in metrics) — worth pinning down before two variants drift.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That's true - I didn't collapse the two variants since semantically they are not identical.

Fixed through the new MemoryPolicyMode from last comment now the mode is:

  1. none -> MemoryPolicyMode::ExplicitNone (memory policy design allowed this "none" as a conversation privacy mode)
  2. missing header -> MemoryPolicyMode::Unspecified (header not present at all, behaves as no explicit memory request)
  3. invalid/blank present value -> MemoryPolicyMode::Unrecognized (just invalid value..)

pub conversation_storage: Arc<dyn ConversationStorage>,
pub conversation_item_storage: Arc<dyn ConversationItemStorage>,
pub conversation_memory_writer: Option<Arc<dyn ConversationMemoryWriter>>,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tiny pattern alignment — the rest of this file uses NoOp* impls so callers can call unconditionally (NoOpResponseStorage, NoOpConversationStorage, etc). A NoOpConversationMemoryWriter would let this field be Arc<dyn ConversationMemoryWriter> (required) instead of Option<...>, and would remove the if let Some(writer) branches that'll otherwise show up in every consumer downstream. Same cost now, less friction later.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Hi Simo I have implemented per your suggestion. Added NoOpConversationMemoryWriter and moved writer plumbing to required Arc in the core path, so callers can invoke unconditionally without Option branching.

This keeps behavior unchanged (NoOp on unsupported backends) while reducing downstream friction.

Comment thread model_gateway/src/app_context.rs Outdated
&router_config,
self.conversation_memory_writer.is_some(),
)
.map_err(AppContextBuildError::InvalidConfig)?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Heads-up: validate_memory_writer_configuration is also called at line 397 in from_config, but with a different available signal — backend_supports_memory_writer(...) (static allow-list) vs self.conversation_memory_writer.is_some() (dynamic Arc check). They can disagree, and a caller using the builder directly (not via from_config) only sees this dynamic branch and skips the backend allow-list check. Consolidating to one call at one lifecycle point would be safer and easier to reason about.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fix this by consolidating to a single call in build now, see model_gateway/src/app_context.rs line 321. Inside validate_memory_writer_configuration at app_context.rs line 691, both signals are now checked in one place.

}

/// Configure memory runtime feature flags for store/recall behavior.
pub fn memory_runtime_config(mut self, config: MemoryRuntimeConfig) -> Self {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Heads-up — this builder method is currently the only way to flip memory_runtime.enabled: main.rs::to_router_config doesn't call it, and bindings/python/src/lib.rs::to_router_config doesn't either, so the flag isn't reachable from the CLI or Python today. If staged rollout is the intent, a sentence in the PR description would set reviewer expectations. If not, adding a --memory-runtime-enabled CLI flag (and the matching Python binding) would close the loop in the same PR.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch!. All similar TODO comment issues mentioned above have been fixed. Also updated the PR description.

@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: fc4860a7f9

ℹ️ 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 model_gateway/src/app_context.rs Outdated
slin1237 added a commit that referenced this pull request Apr 18, 2026
…ector

Both have been the consistent primary authors of recent PRs in these subsystems:

- @zhoug9127 (Daisy): #1168, #1149, #1065, #1061, #976 — mcp + data_connector
- @zhaowenzi (Ziwen): #1174, #1163, #1123 — mcp

Signed-off-by: Simo Lin <linsimo.mark@gmail.com>
@zhoug9127
zhoug9127 requested a review from zhaowenzi as a code owner April 21, 2026 16:33

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/data_connector/src/memory.rs`:
- Around line 277-308: Update the file header "Structure:" comment to reflect
the new PART 3 entry for MemoryConversationMemoryWriter and renumber subsequent
parts (e.g., MemoryResponseStorage now PART 4); locate the top-of-file structure
comment and insert an entry referencing MemoryConversationMemoryWriter (and
adjust part numbers for MemoryResponseStorage and any following PART labels) so
the comment matches the actual section order in the file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2639f38a-db57-4b95-bcb4-62915aedabfc

📥 Commits

Reviewing files that changed from the base of the PR and between b7aed68 and 3f4a560.

📒 Files selected for processing (11)
  • crates/data_connector/src/factory.rs
  • crates/data_connector/src/memory.rs
  • model_gateway/src/app_context.rs
  • model_gateway/src/config/builder.rs
  • model_gateway/src/config/types.rs
  • model_gateway/src/memory/context.rs
  • model_gateway/src/routers/common/header_utils.rs
  • model_gateway/src/routers/conversations/handlers.rs
  • model_gateway/src/routers/openai/context.rs
  • model_gateway/src/server.rs
  • model_gateway/src/service_discovery.rs

Comment thread crates/data_connector/src/memory.rs
Comment thread model_gateway/src/routers/common/header_utils.rs Outdated

@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: c9e162d478

ℹ️ 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 model_gateway/src/routers/common/header_utils.rs Outdated
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from c9e162d to f24d8ed Compare April 21, 2026 18:17
Comment thread model_gateway/src/routers/common/header_utils.rs Outdated
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from f24d8ed to fa3a18b Compare April 21, 2026 19:41
Comment thread model_gateway/src/routers/common/header_utils.rs Outdated
@github-actions github-actions Bot added grpc gRPC client and router changes tests Test changes labels Apr 21, 2026

@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: fa3a18be42

ℹ️ 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 model_gateway/src/app_context.rs
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
…ory-substrate

Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
…ory-substrate

Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
Signed-off-by: Daisy Zhou <zhoug9127@gmail.com>
@zhoug9127
zhoug9127 force-pushed the feat/conversation-memory-substrate branch from b000f54 to b173500 Compare April 21, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data-connector Data connector crate changes grpc gRPC client and router changes model-gateway Model gateway crate changes openai OpenAI router changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants