Summary
On the event backend, the expand_context parameter of POST /api/v2/memories/search has no effect on the response in the default (reranker-less) configuration. The expansion work is performed and then discarded.
Evidence
Responses are byte-identical for expand_context: 0 and expand_context: 5 against a live server (event backend, reranker: null, 2k-episode project) — verified by direct comparison of parsed response bodies.
Mechanism
expand_context threads correctly all the way down: spec → MemMachine.query_search → LongTermMemory._search_scored_event → EventMemory.query, which fetches up to N timeline-neighbor segments per seed (a LATERAL query per direction), decodes and materializes all of them into ScoredSegmentContext.segments.
The only consumer of those contexts is LongTermMemory._search_scored_event, which reads exactly one segment per context (the seed, located by seed_segment_uuid) and exactly one property of it (_episode_uid), plus the score. The neighbor segments are never referenced. The response schema (EpisodicSearchResult) also has no field that could carry context.
So on this path the parameter's entire effect is extra Postgres work and materialization per request.
Where it is not inert: with a reranker configured, the windows feed the reranker's candidate texts, so expand_context does change scoring there; and library callers of EventMemory.query receive the windows directly.
Expected behavior
The declarative backend treats matched episodes as nuclei, attaches timeline-neighbor episodes as context, and folds them into the returned list with a fill-to-limit algorithm (DeclarativeMemory._unify_scored_anchored_episode_contexts): contexts of the best matches are included whole while they fit, then filled by index-proximity to the nucleus until max_num_episodes is reached.
The event backend should do the equivalent: derive the neighbor episodes from the expanded segment windows (each segment carries its _episode_uid) and unify them into the returned episodes the same way, so expand_context returns surrounding context episodes as the parameter implies.
Environment
Observed at current main (231ce17); the consuming code is packages/server/src/memmachine_server/episodic_memory/long_term_memory/long_term_memory.py (_search_scored_event).
🤖 Written by Claude Code (Opus 5) on behalf of @edwinyyyu.
Summary
On the event backend, the
expand_contextparameter ofPOST /api/v2/memories/searchhas no effect on the response in the default (reranker-less) configuration. The expansion work is performed and then discarded.Evidence
Responses are byte-identical for
expand_context: 0andexpand_context: 5against a live server (event backend,reranker: null, 2k-episode project) — verified by direct comparison of parsed response bodies.Mechanism
expand_contextthreads correctly all the way down: spec →MemMachine.query_search→LongTermMemory._search_scored_event→EventMemory.query, which fetches up to N timeline-neighbor segments per seed (a LATERAL query per direction), decodes and materializes all of them intoScoredSegmentContext.segments.The only consumer of those contexts is
LongTermMemory._search_scored_event, which reads exactly one segment per context (the seed, located byseed_segment_uuid) and exactly one property of it (_episode_uid), plus the score. The neighbor segments are never referenced. The response schema (EpisodicSearchResult) also has no field that could carry context.So on this path the parameter's entire effect is extra Postgres work and materialization per request.
Where it is not inert: with a reranker configured, the windows feed the reranker's candidate texts, so
expand_contextdoes change scoring there; and library callers ofEventMemory.queryreceive the windows directly.Expected behavior
The declarative backend treats matched episodes as nuclei, attaches timeline-neighbor episodes as context, and folds them into the returned list with a fill-to-limit algorithm (
DeclarativeMemory._unify_scored_anchored_episode_contexts): contexts of the best matches are included whole while they fit, then filled by index-proximity to the nucleus untilmax_num_episodesis reached.The event backend should do the equivalent: derive the neighbor episodes from the expanded segment windows (each segment carries its
_episode_uid) and unify them into the returned episodes the same way, soexpand_contextreturns surrounding context episodes as the parameter implies.Environment
Observed at current
main(231ce17); the consuming code ispackages/server/src/memmachine_server/episodic_memory/long_term_memory/long_term_memory.py(_search_scored_event).🤖 Written by Claude Code (Opus 5) on behalf of @edwinyyyu.