Module: Clacky::Agent::MemoryUpdater

Included in:
Clacky::Agent
Defined in:
lib/clacky/agent/memory_updater.rb

Overview

Long-term memory update functionality.

Runs at the end of a qualifying task to persist important knowledge into ~/.clacky/memories/. The LLM decides:

- Which topics were discussed
- Which memory files to update or create
- How to merge new info with existing content
- What to drop to stay within the per-file token limit

Architecture:

Memory update runs as a **forked subagent**, NOT inline in the
main agent's loop. The subagent inherits the main agent's history
(so it can see what happened) via +fork_subagent+'s standard
deep-clone, and inherits the same model/tools so prompt-cache is
reused maximally. The subagent runs synchronously; when it returns,
the main agent prints +show_complete+.

This gives us, structurally:
  - Clean main-agent history (no memory_update messages to clean up)
  - Correct visual ordering ([OK] Task Complete is the LAST thing
    printed — the memory-update progress finishes before it)
  - Independent cost accounting (task cost vs. memory update cost)
  - Natural recursion guard (+@is_subagent+ blocks re-entry)

Trigger condition:

- Iteration count >= MEMORY_UPDATE_MIN_ITERATIONS (skip trivial tasks)
- Not already a subagent (no recursion)
- Memory update is enabled in config

Constant Summary collapse

MEMORY_UPDATE_MIN_ITERATIONS =

Minimum LLM iterations for this task before triggering memory update. Set high enough to skip short utility tasks (commit, deploy, etc.)

10
MEMORIES_DIR =
File.expand_path("~/.clacky/memories")

Instance Method Summary collapse

Instance Method Details

#run_memory_update_subagentObject

Run memory update as a forked subagent.

This is called by Agent#run on the success path, AFTER the main loop exits and BEFORE show_complete is printed. It blocks until the subagent finishes, so the visual order is structurally correct:

... task output ...
[progress] Updating long-term memory… (spinner)
[progress finishes]
[OK] Task Complete

Safe to call unconditionally; returns early if preconditions fail. Never raises for “no update needed” — only propagates genuine errors (Clacky::AgentInterrupted for Ctrl+C, other exceptions are caught and logged so memory-update failures never mask the parent task’s result).



68
69
70
71
72
73
74
# File 'lib/clacky/agent/memory_updater.rb', line 68

def run_memory_update_subagent
  return unless should_update_memory?

  with_memory_update_phase do
    run_memory_update_subagent_inner
  end
end

#should_update_memory?Boolean

Check if memory update should be triggered for this task. Only triggers when the task had enough LLM iterations, skipping short utility tasks (e.g. commit, deploy).

Returns:

  • (Boolean)


44
45
46
47
48
49
50
# File 'lib/clacky/agent/memory_updater.rb', line 44

def should_update_memory?
  return false unless memory_update_enabled?
  return false if @is_subagent  # Subagents never update memory

  task_iterations = @iterations - (@task_start_iterations || 0)
  task_iterations >= MEMORY_UPDATE_MIN_ITERATIONS
end