OpenHermit has three memory layers:
- Session history: persisted event log in
session_events - Working memory: session-local summary stored on
sessions - Long-term memory: key/content entries in
memories
Long-term memory is implemented by DbMemoryProvider.
| Field | Meaning |
|---|---|
memory_key |
stable memory ID |
content |
memory text |
metadata_json |
arbitrary metadata |
created_at / updated_at |
timestamps |
content_tsv |
generated PostgreSQL FTS column, created by SQL migration/lazy setup |
Search first uses PostgreSQL tsvector ranking, then falls back to per-word ILIKE over key and content. The fallback matters for partial matches, keys, and non-English text.
Main agent memory tools:
memory_getmemory_listmemory_recallmemory_addmemory_updatememory_delete
Introspection-only tools:
working_memory_updatesession_description_update
At turn start, the prompt can include:
- agent instructions
- recent session history
- current session working memory
- recent long-term memory context from
getContextBlock - skill index
- user/role context
memory.context_entry_limit controls how many recent memory entries are included in the context block.
Introspection is program-triggered and model-executed. It sees recent unsummarized history, previous working memory, current description, and memory tools. It may:
- add/update/delete long-term memories
- update working memory
- update the session description
Config:
{
"memory": {
"context_entry_limit": 10,
"introspection": {
"enabled": true,
"turn_interval": 5,
"idle_timeout_minutes": 10,
"max_tool_calls": 10,
"model": null
}
}
}Compaction is separate from introspection. It reduces model context when history grows too large, preserving recent continuity and summarized older context. It does not decide what belongs in long-term memory.
Memory content is agent-generated or user-requested, but memory lifecycle is runtime-controlled. The runtime decides when introspection runs and what transcript range it sees.