# OpenViking Memory Directories Split by Language: Unify With Custom Templates


OpenViking memory paths ended up with two parallel directory trees: `entities/infrastructure/` and `entities/基础设施/` holding the same kind of content. The cause is in the session commit auto-extraction pipeline, which names directories in the detected conversation language. Editing the memory template fixes the naming at the source; steps below.

## Symptom

`viking://user/<user>/memories/entities/` contained both:

```
entities/infrastructure/   ← dmit.md, surface.md (written by Hermes via viking_remember)
entities/基础设施/         ← backrest_backup.md, legion_wsl.md (auto-extracted by session commit)
entities/services/         ← hermes_gateway_sessions.md
entities/服务/             ← same content, second copy
```

The two write paths use different directory languages: Hermes writes English directories, OpenViking's auto-extraction writes Chinese ones, splitting the same class of content in two.

## Root cause

During session commit, OpenViking detects the output language from conversation content (`_detect_language()` in `session_extract_context_provider.py`). A Chinese conversation sets the template variable `{{ language }}` to zh-CN.

In the memory type YAML templates, the entities directory comes from the `category` field:

```yaml
# prompts/templates/memory/entities.yaml
filename_template: "{{ category }}/{{ name }}.md"

fields:
  - name: category
    description: |
      Category written in {{ language }}.
      {% if language == 'en' %}Use lowercase with underscores, max 3 words.{% else %}Keep it concise and natural in {{ language }}.{% endif %}
```

The language-adaptive instruction makes the LLM write category in Chinese ("基础设施", "服务"), producing Chinese directories. The `name` field already allows Chinese or English, and filenames do not affect path-level consistency, so leave it alone.

## Editing the template

OpenViking supports `memory.custom_templates_dir`: YAML files loaded from this directory override built-in templates of the same name (`MemoryTypeRegistry.load_from_directory(..., replace=True)`).

1. Copy the built-in entities.yaml to the custom directory:

```bash
mkdir -p /path/to/openviking/data/custom_templates
podman cp systemd-openviking:/app/.venv/lib/python3.13/site-packages/openviking/prompts/templates/memory/entities.yaml \
  /path/to/openviking/data/custom_templates/entities.yaml
```

2. Change the category description to be unconditionally English (independent of `{{ language }}`):

```yaml
# custom_templates/entities.yaml
  - name: category
    type: string
    description: |
      ALWAYS English: lowercase with underscores, max 3 words.
      Never use Chinese or any other language for this field, even if the conversation is in Chinese.
    merge_op: immutable
```

Leave the `name` field untouched.

3. Enable it in `ov.conf` (container path `/app/.openviking/ov.conf`):

```json
"memory": {
    "custom_templates_dir": "/app/.openviking/custom_templates"
}
```

4. Restart the service to apply.

## Verification

After the template change, new entities extracted from normal conversations all land in English directories:

| Entity mentioned in chat | Resulting path |
| --- | --- |
| netcup server | `entities/infrastructure/netcup.md` (merged into existing English dir) |
| wireguard tunnel | `entities/networking/wireguard_tunnel.md` |
| PEAK (co-op climbing game with mods) | `entities/game/peak.md` |

No new Chinese directories. Event filenames may still be Chinese (`events/2026/08/12/WireGuard隧道配置完成.md`) — filenames do not affect path-level consistency.

Other memory types (events, preferences, cases, ...) use fixed directory structures (dates, usernames) with no LLM-named directory level, so they need no changes.


---

> Author: Nite  
> URL: https://www.nite07.com/en/posts/openviking-memory-path-language/  

