Skip to content

Default memory_type for direct content creation should probably be Insight, not Pinned #13

@doctatortot

Description

@doctatortot

Observed behavior

POST /v1/memories with a direct-content body (no messages array) hardcodes MemoryType::Pinned as the default when the caller doesn't specify memory_type. After #10, callers can pass memory_type explicitly — but the default still silently pins.

// omem-server/src/api/handlers/memory.rs (after #10)
let memory_type = match body.memory_type {
    Some(s) => s.parse().map_err(OmemError::Validation)?,
    None => MemoryType::Pinned,   // <— this default
};

Why I think this is wrong

Pinned carries a specific behavior: stage_rrf_fusion applies a 1.5× pinned_boost multiplier. The boost only does what it's named for if Pinned is reserved for a curated few — when everything is pinned, the boost applies uniformly to the whole corpus and is effectively a no-op for relative ordering.

The default contradicts the semantic intent of the variant.

How I noticed

I migrated ~170 memories into my instance via the API (just POST /v1/memories with {"content": "..."}) and ended up with 170/170 memory_type: pinned. The retrieval misbehavior I reported in #7 was meaningfully driven by this — the "irrelevant top still scores 1.0" symptom from that issue's body had two causes, and "every memory is pinned" was a bigger driver than the normalization choice fixed in #9.

There's no way for an integrator to know they should pass memory_type=insight unless they read the handler source. The shape of CreateMemoryBody before #10 didn't even surface the field; the default was invisible.

Proposed change

Flip the default to Insight:

let memory_type = match body.memory_type {
    Some(s) => s.parse().map_err(OmemError::Validation)?,
    None => MemoryType::Insight,
};

One line. Existing data untouched. Callers who actually want pinning pass it explicitly.

Compat impact

  • Existing callers using direct-content create: newly-created memories would no longer be boosted in search ranking. They could opt back in with memory_type=pinned.
  • Existing pinned data: untouched. Stays pinned.
  • Message-mode ingestion path (messages: [...]): unaffected. That path goes through IngestPipeline and sets types differently.

Alternative considered: keep Pinned, document the implication

Document loudly in the handler docstring and README that the default is Pinned and that callers doing bulk creation should override it. Cheaper change; relies on integrators reading docs.

I lean toward flipping the default because the principle of least surprise points that way — "what does the API give me by default" should be the normal, unboosted variant, with elevation as an explicit opt-in. But happy to write up the docs path instead if you'd rather minimize behavior change.

Happy to PR whichever direction you pick.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions