LTM 02: Memory Update & Delete
LLM-initiated replacement or deletion of an existing persistent memory,
identified by the ID:N shown in the LLM’s context.
File: src/tools/functionCalls/updateLongTermMemoryTool.ts — class
UpdateLongTermMemoryTool, tool name update_long_term_memory
Mission
Section titled “Mission”When the LLM identifies an existing memory that needs correction, revision,
or removal, it calls update_long_term_memory with the memory’s memory_id,
new memory_content (or empty string to delete), and optionally a
target_user to indicate the memory is personal rather than server-wide.
UpdateLongTermMemoryTool.execute() runs the following sequence:
- Validate parameters (integer ID > 0, content is a string, feature flag on).
- Sanitize content —
sanitizeUnknownTemplatePlaceholders()strips brace-wrapped non-template tokens. Empty string after sanitization = delete. - Resolve target user (if
target_userprovided) — sameresolveUserTarget()lookup as stage 01, but bridge users are rejected outright for personal updates (they only support server-wide memories). - Scope determination —
target_userpresent → personal path; absent → server path. - Privacy / guild membership check (personal path, update only) —
PrivacyLevel.PARTIAL/FULLblocks the update. Target user must be in the guild or DM channel. - Find the memory (personal delete/update) — loads the user’s personal
memories for this lineage and locates the entry matching
memory_id. - DB write —
serverMemoryRepository.updateByIdWithLineage()/personalMemoryRepository.updateByIdForUserAndLineage()for updates;serverMemoryRepository.removeByIdWithLineage()/personalMemoryRepository.removeByIdForUserAndLineage()for deletes. - Notify — send an update or delete embed to Discord.
- Invalidate cache — same paths as stage 01.
Tool arguments (from LLM):
| Arg | Type | Required | Description |
|---|---|---|---|
memory_id | number | yes | Integer ID as shown in context (ID:N). Must be > 0 and a safe integer. |
memory_content | string | yes | Full replacement content. Empty string → delete instead of update. |
target_user | string | when personal | Display name of the memory owner. Absent → server memory path. |
Context required: same as stage 01 (tomoriState, channel, userId).
Output
Section titled “Output”Promise<ToolResult> with data.status indicating outcome:
| Status | Meaning |
|---|---|
memory_updated_successfully | DB update succeeded |
memory_deleted_successfully | DB delete succeeded |
memory_update_failed_not_found | No memory with this ID in the current scope |
memory_update_failed_disabled | self_teaching_enabled is off |
memory_update_failed_privacy_restricted | Target user has PrivacyLevel.PARTIAL/FULL |
memory_update_failed_invalid_scope | Bridge-user personal update attempted; or target not in guild |
memory_update_failed_ambiguous_user | Multiple users matched target_user |
memory_update_failed_user_not_found | No matching user found |
memory_update_failed_invalid_target | Attempted to update personal memory about the bot itself |
memory_update_failed_db_error | DB operation failed |
Side effects
Section titled “Side effects”- DB row updated or deleted — the row matching
(memory_id, server_id, persona_lineage_id)for server memories, or(memory_id, user_id, persona_lineage_id)for personal memories. - Discord embed sent — update embed (amber
MEMORY_UPDATEcolor) or delete embed (redERRORcolor) sent tocontext.channel. - Cache invalidated — same as stage 01:
invalidateTomoriStateCacheorinvalidateUserCacheimmediately after DB success.
Invariants
Section titled “Invariants”After a successful update:
- The row with
memory_idcontainsnewContentas itscontentcolumn. - The TomoriState or user cache for the affected scope has been invalidated.
After a successful delete:
- No row with
memory_idexists in the relevant table for this(server_id / user_id, persona_lineage_id)scope. - The embed shows the deleted content (fetched from the
deletedMemoryreturn value before deletion) for user confirmation.
Scope disambiguation
Section titled “Scope disambiguation”| Condition | Path taken |
|---|---|
target_user absent | Server memory path — update/delete from server_memories scoped to (server_id, persona_lineage_id) |
target_user present and resolved | Personal memory path — update/delete from personal_memories scoped to (user_id, persona_lineage_id) |
target_user is a bridge user | Error — bridge users only support server-wide memories |
target_user resolves to the bot | Error — personal memories about the bot are not supported |
Extension points
Section titled “Extension points”| Surface | Plugin-relevance |
|---|---|
serverMemoryRepository.updateByIdWithLineage() / removeByIdWithLineage() | Internal — scope is fixed by (server_id, persona_lineage_id); no plugin seam for custom scoping within this method. |
personalMemoryRepository.updateByIdForUserAndLineage() / removeByIdForUserAndLineage() | Internal — same as above for personal scope. |
Embed color (ColorCode.MEMORY_UPDATE vs ColorCode.ERROR) | Internal — color codes are defined in src/utils/misc/logger.ts; not a plugin seam. |
Related docs
Section titled “Related docs”- Stage that creates the memories updated here: →
ltm/01-ltm-create.md - Context-build stages that read these memories: → server / personal
- Privacy level schema: →
src/types/db/schema.ts(PrivacyLevelenum) - Bridge user detection: →
src/utils/bridges/index.ts