RAG and agent memory usually mean three systems: a cache, a vector database, and a search index — with the same facts in all three, drifting apart. kevy has vector KNN, BM25 full-text and a change feed in the engine, over the keys you already wrote.
The expensive part of a RAG stack is not the search. It is keeping three copies of the truth in step: you write a document, then you have to remember to embed it, index it, and invalidate the cache. Every one of those is a place to forget.
In kevy the index is a declaration, not a pipeline. You tell the engine which keys and which field, and the write path keeps the index current. There is nothing to run afterwards and nothing to fall behind.
What kevy does not do is produce the embedding. There is no model in the engine and there will not be one — inference does not belong in a storage engine, and pretending otherwise would tie your vector format to our release cycle. You bring the vector; kevy stores it, indexes it and searches it.
KNN over a field of the keys you already write. Declared once; the write path keeps it current, with nothing to sync.
IDX.CREATE idx:sem ON PREFIX doc: FIELD vec TYPE vector KIND ann DIM 768 DISTANCE cosine M 16 EF 200
-> OKThe engine backfills existing keys, answering INDEXBUILDING while it does.
HSET doc:4410 title "Ada on pipelining" vec "<768 f32, little-endian>"IDX.QUERY idx:sem KNN "<query vector>" LIMIT 10
-> 1) doc:4410
2) doc:9982Cost & limits The index is HNSW, which is approximate: recall is a tuning parameter (EF), not a guarantee. The first build is O(N) over the matching keys — plan it, do not discover it. And there is no embedding model: you bring the vector. The vector guide has the tuning knobs.
BM25 over the same keys, and a hybrid query that fuses the text ranking with the vector ranking in one command.
IDX.CREATE idx:ft ON PREFIX doc: FIELD title TYPE str KIND text
-> OKIDX.QUERY idx:ft MATCH "pipelining"
-> 1) 1) "doc:1"
2) "0.2877" # the BM25 scoreIDX.QUERY HYBRID idx:ft MATCH "pipelining" idx:sem KNN "<vector>" LIMIT 20 RRFK 60Cost & limits Indexes are paid for on every write to a matching key — the right trade for read-heavy retrieval, the wrong one for a key you rewrite thousands of times a second. Tokenisation (including CJK) and where BM25 stops are in the text guide.
Tail every write from another process — embed on change, not on a schedule, and resume from where you stopped.
# kevy.toml
[feed]
enabled = trueFEED.SHARDS -> (integer) 16
FEED.TAIL 0 -> 1) (integer) 1 # generation
2) (integer) 1 # offsetFEED.READ 0 1 0 COUNT 2 -> the writes themselves, replayableCost & limits The feed is per shard: FEED.SHARDS tells you how many cursors you own, and your consumer tracks one offset per shard. It is off by default — flipping [feed] on is what buys the write-path bookkeeping. The change-feed guide covers resuming across restarts.
llms-full.txt is one fetch: every command with its real cost and its real deviation from Redis, plus the complete text of every guide. It is generated from the engine's own verb table, so it cannot drift from what the server does.