Skip to content

Recall misses relevant memories with self-hosted Supermemory when /v4/profile differs from hybrid search #59

Description

@Sinicyn78

Summary

With self-hosted Supermemory, Codex automatic recall can miss relevant memories even though the memory is present and retrievable through /v4/search with searchMode: "hybrid".

I reproduced this in VS Code Codex with codex-supermemory on Windows. Automatic capture works, but recall via the hook can return fewer results than a direct hybrid search. A second issue compounds this: recall formatting truncates each result to the first 300 characters, so a relevant fact found deeper inside a long chunk may still not reach the model.

Environment

  • Windows 11
  • VS Code Codex
  • codex-cli 0.147.0-alpha.6.5
  • codex-supermemory 1.0.17
  • self-hosted Supermemory (local server)
  • recallMode: "direct"

What works

Automatic capture works correctly. Example debug log:

flush: start
addMemory: start: {"containerTag":"repo_hookroulette__16d99fa5e1592aa8", ...}
addMemory: success: {"id":"..."}
flush: captured entries

The saved fact is also retrievable directly from self-hosted Supermemory.

Reproduction

  1. Save a fact in one Codex session, e.g.:
For this project, remember the control phrase ORANGE-7319.
  1. Let the Stop hook capture the session.

  2. Start a new Codex session and ask:

What control phrase do you remember for this project?
  1. Automatic recall can return fewer results than a direct hybrid search.

Observed hook log before patch:

recall: start: {...}
recall: done: {"matchCount":3,"freshCount":3,"seenCount":0}
recall: emit context: {...}

But a direct request to the same container using:

{
  "q": "What control phrase do you remember for this project?",
  "containerTag": "repo_hookroulette__16d99fa5e1592aa8",
  "searchMode": "hybrid",
  "limit": 5
}

returned 4 results, with the relevant ORANGE-7319 result present as the 4th match.

Root cause found in the Codex integration

src/services/hookRecallClient.ts calls /v4/profile and returns immediately if searchResults is non-empty:

if (profileResponse.ok) {
  profileResult = normalizeProfileResponse(await profileResponse.json());

  if ((profileResult.searchResults?.results?.length ?? 0) > 0) {
    return profileResult;
  }
}

On my self-hosted instance, /v4/profile returned 3 search results, while /v4/search with searchMode: "hybrid" returned 4, including the relevant fact. Because of the early return, the hybrid search fallback never ran.

Changing the logic so /v4/profile is used for static/dynamic profile data, while /v4/search with searchMode: "hybrid" is always used for recall search, fixed the missing-result issue.

After patching:

recall: done: {"matchCount":4,"freshCount":4,"seenCount":0}
recall: emit context: {...}

Second issue: truncation hides facts inside long chunks

src/hooks/recall.ts currently formats each recalled item by taking only the first 300 characters:

const MAX_RESULT_CHARS = 300;
...
const text = item.memory.replace(/\s+/g, " ").slice(0, MAX_RESULT_CHARS);

This can discard the actually relevant fact even when semantic search correctly retrieves the chunk.

In my test, ORANGE-7319 was present deeper in the retrieved chunk, but the injected recall context contained only the first 300 characters. Increasing the window allowed the model to recall it successfully. A query-aware excerpt around the relevant match would be better than a fixed prefix.

Additional observation

Searching only the canonical project container first was much faster and avoided hook timeout pressure. Searching all legacy/read containers and then running hybrid fallback for each caused the hook to exceed the UserPromptSubmit time budget in my test.

Suggested changes

  1. Do not treat non-empty /v4/profile.searchResults as authoritative for self-hosted recall.
  2. Use /v4/search with searchMode: "hybrid" as the recall search source, while keeping /v4/profile for profile facts.
  3. Prefer canonical-container-first recall, with legacy containers as a secondary fallback.
  4. Replace fixed slice(0, 300) truncation with a query-aware excerpt/window around the relevant part of the chunk.

Result after local patch

After applying these changes, cross-session recall worked reliably in VS Code Codex. A fact saved in one session and not written to project files was recalled correctly in a fresh session from Supermemory.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions