Skip to content

memvec://

Pure in-process vector store accessible via the memvec:// URI scheme. The component is keyed by collection name through the process-global registry (pkg/rag/store.GetOrCreateInMemoryStore), so an upsert at memvec://kb/upsert is visible to a rag-retrieve step configured with store: memory, collection: kb AND to a rag-store: { store: memory, collection: kb } ingest step. All three surfaces resolve through the same registry.

Use memvec:// for development, tests, and demos — RAG with no external vector DB and no network round-trip. Data does not persist across process restarts.

Picking the right ingest writer: memvec://<collection>/upsert and rag-store: { store: memory, collection: <same> } are interchangeable for in-process flows. Use the rag-store form when you're already inside a rag-* pipeline; use the memvec:// target when you want the URI directly (e.g. when you compute embeddings yourself in a transform and skip rag-embed).

URI shape

memvec://<collection>/<operation>?topK=N

Producer-only — CreateConsumer returns an error.

Token Description
<collection> Required — collection name. Each collection is an independent in-memory store.
<operation> Optional — upsert (default), search, delete.

Parameters

Param Type Default Producer/Consumer/Both Description
topK integer 5 Producer Search result count.

Body contracts

The body types are strict (typed Go values, not JSON):

Operation Body type Notes
upsert []*rag.Embedding Typically the output of a rag-embed step.
search []float32 A single query vector — typically the output of rag-embed on a string.
delete []string Chunk IDs to remove.

If the body shape doesn't match, the producer returns an error naming the expected type.

Headers

Written by the producer

Header Description
memvec.collection Collection name.
memvec.operation Operation just executed.
memvec.upserted upsert only — count.
memvec.results search only — count.
memvec.deleted delete only — count.

search also sets the body to []*rag.SearchResult (the in-memory store's native shape).

Examples

End-to-end RAG with no external store:

workflows:
  - id: ingest
    trigger: { uri: direct://ingest }
    steps:
      - rag-chunk: { strategy: recursive, chunkSize: 512 }
      - rag-embed: { provider: openai, model: text-embedding-3-small }
      - target: memvec://kb/upsert

  - id: ask
    trigger: { uri: direct://ask }
    steps:
      - rag-retrieve:
          store: memory
          collection: kb
          top-k: 5
      - rag-generate: { llm: openai/gpt-4o }

Note the consumer of the embeddings here uses memvec://kb/upsert while retrieval reads via rag-retrieve with store: memory. They share the same backing data because both go through store.GetOrCreateInMemoryStore("kb") — the same registry, keyed by collection name. The equivalent rag-store: { store: memory, collection: kb } form resolves through the same registry, so the two ingest writers are interchangeable.

Search directly (skipping rag-retrieve):

- rag-embed: { provider: openai, model: text-embedding-3-small }
- target: memvec://kb/search?topK=10

Delete by ID list:

- set-body:
    starlang: '["chunk-1", "chunk-2"]'
- target: memvec://kb/delete

Behavior notes

  • Process-local, ephemeral — there is no file persistence. Restart the binary and the store is empty.
  • Shared with RAG memory backend — collection name is the join key. This is by design — letting you switch between memvec:// and rag-retrieve store: memory interchangeably.
  • No filter / metadata search — search is pure vector similarity. Use memx:// or a dedicated vector DB when you need hybrid or filtered retrieval.
  • Goroutine-safe — the underlying InMemoryStore uses a mutex; concurrent upserts and searches are fine.

Source

pkg/component/memvec/memvec.go, pkg/rag/store/memory.go

See also