Memory and skills
Long-term memory as Markdown notes, the user profile, untrusted notes, semantic search and background review; skills as SKILL.md folders.
Agents get the memory and skills toolsets by default, along with core, schedule, delegate and board. A config that lists toolsets itself gets exactly that list (for example toolsets: [core] turns memory and skills off), and the prompt only mentions memory or skills when the agent has the matching toolset.
Memory#
- Memory is one Markdown file per note in
agents/<name>/memory/, withtitle,tags,createdandupdatedin its frontmatter, plus where it came from (source,session,trust). Habakkuk saves durable facts, preferences and decisions there withmemory_saveand finds them withmemory_search(SQLite FTS5, bm25 ranking, and semantic search when embeddings are configured). Edit or add notes by hand at any time; the index picks the change up on the next search. Forgotten notes move tomemory/.trash/. Text that looks like a key, token, password or card number is refused. - The user profile is
agents/<name>/USER.md: a short file of## Sectionblocks with durable facts about you (name, where you live, how you like to be helped). Every new session starts with it in the prompt. The agent edits one section at a time withuser_profile_update; you can edit it by hand. - In chat,
/remember <text>saves your words as a note and/forget <what or slug>removes one (several matches are listed rather than guessed). - Untrusted notes. A note saved in a turn that read outside content (web pages, search results, MCP and other network tools, an email inbox channel) is marked
trust: untrustedand shown to the model with a warning, so text planted in a page cannot quietly become something the agent believes. Such turns cannot change USER.md at all.habakkuk memory trust <slug>vouches for a note.
A note looks like this:
---
title: Coffee preference
tags: [food, preferences]
created: "2026-11-06T09:12:00Z"
updated: "2026-11-06T09:12:00Z"
---
Flat white with oat milk, no sugar.
From the terminal:
habakkuk memory # an agent's memories, newest first
habakkuk memory search coffee # search them
habakkuk memory show <slug> # one note, with where it came from
habakkuk memory forget <slug> # move a note to the memory trash
habakkuk memory trust <slug> [yes|no] # vouch for a note written from outside content
habakkuk memory profile # the agent's profile of you (USER.md)
habakkuk memory log # what the background review changed
Each new session's prompt lists the most recent memory titles and every skill's description, as a snapshot taken when the session starts.
Semantic search, review and the nightly pass#
Optional extras, in a memory: section:
memory:
embeddings: {provider: openai, model: text-embedding-3-small} # or a provider with preset: ollama, or gemini
review: true # turn idle conversations into notes and profile updates
review_model: anthropic/claude-sonnet-5-5 # default: each agent's last fallback model
review_idle: 15m
nightly: "03:30" # merge near-duplicate notes, archive stale ones; or off
stale_days: 365 # -1 never archives; notes tagged pinned or keep are never archived
With embeddings, notes are embedded when saved (cached by content, so unchanged notes are never sent again) and search blends keyword and meaning matches; if the embedding service fails, search carries on with keywords. With review: true, habakkuk serve reviews each conversation once it has been quiet for review_idle, saving what is worth keeping with source: review, and writes one line per review to memory/.review.log (habakkuk memory log). The nightly pass merges near-duplicate notes and archives notes neither updated nor read for stale_days.
Architecture: memory describes the index, ranking, provenance and crash safety.
Memory history and undo#
Nothing an agent remembers changes silently. Every change to a memory note, USER.md, IDENTITY.md or one of the agent's own skills is recorded in $HABAKKUK_HOME/history.db with the text before and after, who made it (the agent through a tool such as memory_save or set_identity, you through a chat command, the CLI or the dashboard, the background review, the skills curator, or a hand edit), the session, whether external content had entered that turn, and when. Edits you make to the files yourself are picked up too: when the index next looks at a note, and once a minute for everything else while habakkuk serve runs.
habakkuk memory history [-agent A] [-file NAME] [-since 7d] # newest first, with change ids
habakkuk memory diff <id> # one change as a unified diff
habakkuk memory restore <id> [-after] # put back the text before it (or after it, to redo)
habakkuk memory pin <slug> | skill:<name> | profile # background jobs leave it alone
habakkuk memory unpin <slug> | skill:<name> | profile
habakkuk memory pins
- Undo is a change too. Restoring records a new change that names the one it went back to, so an undo can itself be undone. Restoring a version in which the file did not exist moves it to a
.trash/folder beside it. For a skill the history holdsSKILL.md; a skill the curator merged away or archived gets its supporting files back withhabakkuk skills restore NAME. - In chat,
/memorylists the last 10 changes for the conversation's agent with their short ids, and/undo-memory <id>undoes one. The agent has a read-onlymemory_historytool, so you can ask it "what did you change in my profile?". - Pinned notes,
USER.mdand skills are never rewritten, merged away or archived by the background review, the nightly pass or the skills curator; you and the agent can still edit them. - Crash-safe. A change is first written to the history as pending, then the file is replaced atomically, then the change is marked done. After a crash the pending change is kept if the file holds the new text and dropped if it does not, so the history never shows a change that did not happen and never misses one that did.
- Retention. Changes are kept for
memory.history_days(default 90,-1keeps everything) and pruned by the same maintenance pass asretention.days. The newest version of every file that still exists is always kept. Content is stored once per distinct text and compressed. - The dashboard API has the same:
GET /api/memory-history/{agent},GET /api/memory-history/{agent}/{id}andPOST /api/memory-history/{agent}/{id}/restore(docs/API.md).
memory:
history_days: 90 # -1 keeps all history
Skills#
Skills are folders with a SKILL.md (frontmatter name and description, then instructions) and optional supporting files. Put shared skills in $HABAKKUK_HOME/skills/<name>/ and an agent's own in agents/<agent>/skills/<name>/, which wins on a name clash. Habakkuk loads a skill with skill_view before a task it covers and can write its own with skill_save (the previous version is kept as SKILL.md.bak).
---
name: weekly-report
description: Write the weekly report from the board and the week's sessions.
---
1. ...
The folder name is the skill name and must be lower-case letters, digits and hyphens (up to 64 characters).
- In a chat,
/skill NAME [request]runs one explicitly,/skillslists them, and/learn <topic, URL or path>has the agent study a source and write a new skill.habakkuk run -skill NAME [request]does the same from the terminal. - Installing. Install skills and plugins from GitHub, URLs, local paths or registries with
habakkuk skills installandhabakkuk plugins install; installed skills are untrusted untilhabakkuk skills approve. See Plugins, outside skills and the MCP catalog. - Curator. With
skills.curate: daily | weekly | monthly,habakkuk servemerges near-duplicate skills the agents wrote and archives ones not loaded forskills.archive_after_days(default 90), with backups;habakkuk skills restore NAMEundoes a change andhabakkuk skills curate [-dry-run]runs it by hand.
skills:
registries:
- {name: team, url: "https://skills.example.com/index.json"}
curate: weekly # off | daily | weekly | monthly
archive_after_days: 90
Architecture: skills has the details.