Tutorial 4: Long-term memory with Milvus
malac’s memory works out of the box as Markdown files. In this tutorial you add a local Milvus so malac can search memories by meaning and recall relevant ones automatically, then watch a fact saved in one session shape the next.
You need Docker, malac from tutorial 1, and an embedding model: either Ollama locally or an OpenAI key.
Run Milvus
Section titled “Run Milvus”-
Start Milvus standalone. In a directory where Milvus may keep its data:
mkdir -p ~/milvus && cd ~/milvuscurl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.shbash standalone_embed.sh startThe script pulls the Milvus image and starts a container listening on port 19530. The first start takes a minute.
-
Check the REST API. malac uses Milvus’s REST API v2:
curl -s -X POST http://localhost:19530/v2/vectordb/collections/list -d '{}'{"code":0,"data":[]}
Configure embeddings and the collection
Section titled “Configure embeddings and the collection”-
Pick an embedding model. With Ollama:
ollama pull nomic-embed-text -
Add the memory settings to
~/.malac/config.toml:[providers.local]kind = "openai"base_url = "http://localhost:11434/v1"[memory.vector]url = "http://localhost:19530"collection = "malac_memory"[memory.embeddings]provider = "local"model = "nomic-embed-text"With OpenAI instead, leave out
[providers.local]and useprovider = "openai"andmodel = "text-embedding-3-small".If malac’s daemon is already running, restart it so every tab loads the new settings:
malac daemon restart. -
Index what you already have. If you saved memories before, put them in the collection. malac creates it on first use:
malac memory reindexindexed 0 memoriesZero is fine on a fresh install.
Save memories
Section titled “Save memories”-
Make a project and start a session.
mkdir -p ~/memo-demo && cd ~/memo-demo && git init -qmalac -
Tell malac a few things worth remembering.
Remember for this project: we use pytest, never unittest, and tests livein tests/. And remember for me everywhere: I prefer short commit messagesin the imperative mood.The memory tools never ask for permission:
● memory_save test-conventions⎿ Saved memory `test-conventions` to /Users/you/memo-demo/.malac/memory/test-conventions.md● memory_save commit-style⎿ Saved memory `commit-style` to /Users/you/.malac/memory/commit-style.mdThe first is a project memory, stored in the repository’s
.malac/memory/. The second is global, in~/.malac/memory/. Each save also embedded the memory into Milvus. -
Look at the files. Exit the session (
/exit) and read one:cat .malac/memory/test-conventions.md---name: test-conventionsdescription: Tests use pytest (never unittest) and live in tests/updated: 2026-10-25T14:10:03.512+00:00---This project uses pytest, never unittest. Tests live in tests/.malac memory[Global] commit-style: Prefers short commit messages in the imperative mood /Users/you/.malac/memory/commit-style.md[Project] test-conventions: Tests use pytest (never unittest) and live in tests/ /Users/you/memo-demo/.malac/memory/test-conventions.mdThe files are the source of truth. You can edit them by hand; run
malac memory reindexafterwards so the vectors follow.
Recall
Section titled “Recall”-
Search by meaning. The query shares no keywords with the memory:
malac memory search how should I check that my code works0.62 test-conventions: Tests use pytest (never unittest) and live in tests/The number is the cosine similarity. Without Milvus, the same search falls back to keywords and would find nothing here.
-
Let auto recall do it. Start a fresh session and ask for something related, without mentioning the conventions:
cat > slug.py <<'EOF'def slugify(text):return "-".join(text.lower().split())EOFmalac -y -p add tests for slugifymalac creates
tests/test_slug.pywith pytest-style test functions and runspytest(install it withpython3 -m pip install pytestif you want the run to pass), because the prompt was embedded and the matching memory was attached to it before the model saw it. -
See what was attached. The recalled memories are part of the prompt in the transcript:
malac sessions # the newest session is first; copy its idmalac sessions show <id>main 019a2c11-… · lora/default · 2026-10-25 14:14› <recalled-memories>...Up to
memory.recall_limitmemories (default 5) with a similarity of at least 0.4 are attached to each prompt of 8 characters or more.
Clean up
Section titled “Clean up”malac memory # list what is savedrm .malac/memory/test-conventions.md # forget by deleting the file…malac memory reindex # …and re-sync the collectionOr ask malac to forget something (“forget the commit style memory”); memory_forget deletes the file and its vector. Stop Milvus with bash ~/milvus/standalone_embed.sh stop.
Zilliz Cloud instead of Docker
Section titled “Zilliz Cloud instead of Docker”Replace [memory.vector] with your cluster’s public endpoint and an API key:
[memory.vector]url = "https://<cluster-id>.<region>.zillizcloud.com"token_env = "ZILLIZ_API_KEY"database = "default"collection = "malac_memory"Everything else in this tutorial stays the same. See Vector memory with Milvus.
Next: Running malac unattended.
malac is created by lobirus and released under the MIT license. About malac