Summary
When using OpenViking with local Ollama models, the memory pipeline is not reliably usable out of the box:
session -> extract may fail internally because the LLM response parser assumes a dict-like payload.
- Even when the server stays up, extraction can return
[], so memory write/search is not actually usable without a fallback path.
In my environment, I had to patch the extractor to tolerate list-shaped payloads and add a fallback resource-based memory capture path on the OpenClaw side to make the system practically usable.
Environment
- Host: macOS (Apple Silicon)
- OpenViking: latest pip package as of 2026-03-15
- Runtime:
openviking-server --config ~/.openviking/ov.conf
- Embedding model via Ollama OpenAI-compatible API:
bge-m3:latest
- Chat/VLM model via Ollama OpenAI-compatible API:
llama3.1:latest
- OpenClaw plugin integration on top, but the core issue reproduces at the OpenViking server / extractor layer
Config used
{
"storage": {
"workspace": "~/.openviking/workspace"
},
"embedding": {
"dense": {
"provider": "openai",
"api_base": "http://127.0.0.1:11434/v1",
"api_key": "ollama-local",
"dimension": 1024,
"model": "bge-m3:latest"
}
},
"vlm": {
"provider": "openai",
"api_base": "http://127.0.0.1:11434/v1",
"api_key": "ollama-local",
"model": "llama3.1:latest"
},
"log": {
"level": "INFO",
"output": "stdout"
}
}
Reproduction
- Start server:
openviking-server --config ~/.openviking/ov.conf
- Create a session:
curl -X POST http://127.0.0.1:1933/api/v1/sessions
- Add a user message:
curl -X POST http://127.0.0.1:1933/api/v1/sessions/<session_id>/messages \
-H 'Content-Type: application/json' \
-d '{"role":"user","content":"用户偏好:回答要专业、简洁、高执行力,少废话。"}'
- Extract:
curl -X POST http://127.0.0.1:1933/api/v1/sessions/<session_id>/extract \
-H 'Content-Type: application/json' \
-d '{}'
Actual behavior
Observed one or both of the following:
A. Internal parser failure
Server log included errors like:
Memory extraction failed: 'list' object has no attribute 'get'
and later also:
Memory extraction failed: 'str' object has no attribute 'get'
This suggests the extractor path assumes parse_json_from_response(...) always returns a dict with a memories key, but local-model outputs may parse into a list or other JSON shapes.
B. Extract succeeds but returns empty result
The HTTP API returns 200, but with:
{"status":"ok","result":[]}
and then semantic search over viking://user/memories returns no memories.
So from an operator perspective, the pipeline looks healthy but memory extraction is not practically working.
Expected behavior
- Extractor should robustly accept common structured-output variants from local models (at minimum dict/list normalization, plus safe rejection of malformed scalars).
- If extraction produces no valid memory candidates, there should be clearer diagnostics and ideally an official fallback or degraded-mode path.
- It would help if the docs explicitly stated which local models / output formats are currently reliable for memory extraction.
Local patch that improved behavior
A minimal local change that fixed one of the crashes was normalizing list output before iterating memories:
data = parse_json_from_response(response) or {}
if isinstance(data, list):
data = {"memories": data}
elif not isinstance(data, dict):
logger.error("Memory extraction parse failed: non-dict payload: %r", data)
data = {}
This avoided at least the 'list' object has no attribute 'get' crash.
Why this matters
For local/self-hosted users, the main value proposition is exactly this setup: Ollama + OpenViking + local agent memory. Right now, the server can appear healthy while the memory extraction path is effectively unusable unless the operator patches around it.
If useful, I can also provide the fallback resource-memory workaround I implemented on the client side, but I think the main upstream issue is the extractor robustness and the lack of clear degraded-mode behavior.
Summary
When using OpenViking with local Ollama models, the memory pipeline is not reliably usable out of the box:
session -> extractmay fail internally because the LLM response parser assumes a dict-like payload.[], so memory write/search is not actually usable without a fallback path.In my environment, I had to patch the extractor to tolerate list-shaped payloads and add a fallback resource-based memory capture path on the OpenClaw side to make the system practically usable.
Environment
openviking-server --config ~/.openviking/ov.confbge-m3:latestllama3.1:latestConfig used
{ "storage": { "workspace": "~/.openviking/workspace" }, "embedding": { "dense": { "provider": "openai", "api_base": "http://127.0.0.1:11434/v1", "api_key": "ollama-local", "dimension": 1024, "model": "bge-m3:latest" } }, "vlm": { "provider": "openai", "api_base": "http://127.0.0.1:11434/v1", "api_key": "ollama-local", "model": "llama3.1:latest" }, "log": { "level": "INFO", "output": "stdout" } }Reproduction
openviking-server --config ~/.openviking/ov.confActual behavior
Observed one or both of the following:
A. Internal parser failure
Server log included errors like:
and later also:
This suggests the extractor path assumes
parse_json_from_response(...)always returns a dict with amemorieskey, but local-model outputs may parse into a list or other JSON shapes.B. Extract succeeds but returns empty result
The HTTP API returns
200, but with:{"status":"ok","result":[]}and then semantic search over
viking://user/memoriesreturns no memories.So from an operator perspective, the pipeline looks healthy but memory extraction is not practically working.
Expected behavior
Local patch that improved behavior
A minimal local change that fixed one of the crashes was normalizing list output before iterating memories:
This avoided at least the
'list' object has no attribute 'get'crash.Why this matters
For local/self-hosted users, the main value proposition is exactly this setup: Ollama + OpenViking + local agent memory. Right now, the server can appear healthy while the memory extraction path is effectively unusable unless the operator patches around it.
If useful, I can also provide the fallback resource-memory workaround I implemented on the client side, but I think the main upstream issue is the extractor robustness and the lack of clear degraded-mode behavior.