long-term-memory
Skill0 starsChanged 2 months agoMITView on GitHub
Persistent long-term memory with automatic lifecycle management. Use memory_tool to store typed user facts, conversation_search to find past context, and a value-scored lifecycle (importance/freshness/activity) that keeps, compresses, archives, or deletes memories over time. Automatically detects memory-worthy information and maintains continuity across sessions.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- XiaoFeiCode/DeepResearchAgenttheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- XiaoFeiCode/DeepResearchAgent★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
25 rules. About 0 are common, 13 are distinctive, and 12 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈13
Distinctive · estimate
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
Layered injection (tiered loading): only hot-tier memories (no | archived, and plans without | status: completed) are auto-injected into …
- Very specific: line 44
Topic-correlated injection (optional, future): when the platform supports it, inject only [project]/[context] memories whose tags relate to …
- Very specific: line 83
Always hot: [identity] name and birthday — never archive.
- Very specific: line 84
Name changes: if the user changes their name or how they want to be addressed, edit the name memory to update it (optionally keep the old …
- Very specific: line 88
Hot tier cap: When hot memories exceed ~20, it is time to consolidate.
- Very specific: line 90
Large injected list: if the injected list becomes unwieldy (roughly 30+ memories), prioritize by scanning [!] first, then active …
- Distinctive: line 128
Every memory follows this structure:
- Very specific: line 161
Add [!] for memories that are critical to user identity or frequently needed.
- Very specific: line 182
Date format: use YYYY-MM (month granularity, e.g.
- Distinctive: line 213
When to edit rather than create:
- Distinctive: line 229
When merging two memories, edit the one with the lower ID (likely older, keeps the memory ID stable for consistent referencing) and delete …
- Distinctive: line 268
If you're not sure whether something is memory-worthy, don't store it.
- Distinctive: line 270
Always respond in the user's language.
- Distinctive: line 276
When the user asks about something from the past:
- Very specific: line 283
Use 2-3 different keyword combinations with conversation_search:
- Distinctive: line 337
Partially redundant → compress naturally: Only when you can cut words WITHOUT losing meaning.
- Distinctive: line 339
Unnecessary → delete, as a LAST resort: Delete only what is truly valueless: factually wrong, fully superseded with zero residual value, or …
- Distinctive: line 358
No score threshold ever forces a deletion.
- Distinctive: line 384
When compression IS natural:
- Distinctive: line 406
Run a lifecycle pass when ANY of these is true:
- Very specific: line 421
Deletion is permanent and irreversible: Before deleting, confirm the fact has zero residual value AND that it can't be recovered from …
- Very specific: line 478
If memory_tool returns an error, note it but don't retry more than once.
- Very specific: line 479
If conversation_search returns empty, try 2 more keyword variations before giving up.
- Distinctive: line 480
If uncertain whether to remember, err on the side of not remembering — user can always tell you to remember later.
- Distinctive: line 486
When taking over from a previous memory system, existing memories may not follow this format.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Long-Term Memory Skill
A lightweight memory system that works with built-in tools only. Inspired by claude-mem (progressive disclosure), agentmemory (typed classification), claude-brain (single source of truth), and Operit AI (two-tier memory architecture).
Required Tools (Interface Contract)
This skill assumes your platform provides four built-in tools. The rules below do not depend on any implementation detail, but the tools must exist — or you must map them to close equivalents on your platform before relying on this skill:
| Tool | Assumed interface | If missing, map to |
memory_tool | create(content), edit(id, content), delete(id), list(filter) → defaults to hot-tier memories; filter="archived" returns cold-tier; search(query) → full-store lookup | Platform memory feature (e.g. Claude Code Memory, Cursor Memories) or a user-scoped notes file. If list/search unavailable → fall back to full injection (see note below) |
conversation_search | search(query) → timestamped summary snippets from past conversation transcripts | Platform chat-history search, or manual scan of recent transcripts |
recent_chats | list(limit) → recent conversation titles/topics | Platform chat-history list |
get_time_info | Returns today's date | Platform date/time tool or system clock |
Injection format (compact): hot-tier memories are injected one per line as
id|content — e.g. 1|[identity][!]User's name is Alex. No JSON wrapping.
Layered injection (tiered loading): only hot-tier memories (no
| archived, and plans without | status: completed) are auto-injected into
every conversation. Cold-tier memories (| archived, or
status: completed plans) are NOT injected; pull them on demand via
memory_tool(action="list", filter="archived") or conversation_search.
Fallback: if the platform cannot provide
list/search, revert to full injection of all memories every conversation (previous behavior) — note this mapping once and proceed.
Topic-correlated injection (optional, future): when the platform supports
it, inject only [project]/[context] memories whose tags relate to the
current topic. Ignore if unsupported.
If you map a tool to a different name, note the mapping once and proceed — every rule below is expressed in terms of the four logical tools above.
Tool Roles (Critical Distinction)
These two tools serve DIFFERENT purposes. Do not confuse them:
| Tool | What it accesses | When to use |
memory_tool | Persistent long-term memories — facts deliberately stored about the user. Hot-tier memories auto-injected; cold-tier pulled on demand. | Creating, editing, deleting, listing, searching memories. |
conversation_search | Past conversation transcripts — raw dialogue history, not curated memories. | Finding context that was discussed but NOT formally stored as a memory. |
Key rule: memory_tool is the "source of truth" for what you know about the user. conversation_search is for forensic deep-dives when the memory store doesn't have the answer.
Important limitation: memory_tool's list/search cover the memory store itself; conversation_search covers raw dialogue history. To check for duplicates, scan the injected hot-tier list (shown every conversation) plus memory_tool(list) results. If the store grows large, pull cold-tier memories on demand rather than keeping them injected.
IDs: injected memories appear one per line as id|content (e.g. 1|[identity][!]User's name is Alex). Use that exact id for edit and delete.
Memory Tiers: Hot vs Cold
Inspired by Operit AI's two-tier architecture, adapted for this lightweight system. Both tiers use memory_tool — the difference is how the AI treats them, not which tool stores them:
| Tier | Tool | What lives here | Access | Size |
| 🔥 Hot | memory_tool | Identity, core preferences, active plans, key decisions | Auto-injected every conversation | ~15-20 max |
| ❄️ Cold | memory_tool (list/search) + conversation_search | Completed plans, old context, historical lessons, past conversations | NOT injected — pulled on demand via memory_tool(list, filter=archived) or conversation_search | Unlimited |
Hot Tier Rules
Hot-tier memories are injected every conversation. Cold-tier memories are NOT injected (pull on demand — see Required Tools). Hot tier means these are the ones you actively prioritize. Keep them lean and essential:
- Always hot:
[identity]name and birthday — never archive. Other identity facts (role, location) may be archived when superseded. - Name changes: if the user changes their name or how they want to be addressed,
editthe name memory to update it (optionally keep the old name as a short note). Never delete or archive a name memory — it always exists, it just gets updated. - Usually hot:
[preference][!],[project][!],[decision][!]— what the user currently cares about most. - Conditionally hot:
[plan]items withstatus: not startedorstatus: in progress.
Hot tier cap: When hot memories exceed ~20, it is time to consolidate. Merge related ones with edit, and downgrade low-priority ones to cold.
Large injected list: if the injected list becomes unwieldy (roughly 30+ memories), prioritize by scanning [!] first, then active plans/projects, then the rest — and run a consolidation pass (see Memory Lifecycle) to shrink it.
Cold Tier Rules
These are NOT injected into conversations. Pull them on demand via memory_tool(action="list", filter="archived") or conversation_search when the topic comes up:
[plan]with| status: completed→ cold (automatic — no extra marker needed)- Any memory with
| archived→ cold (explicit — used by types without a done-state)
Why asymmetric? Plans have a natural lifecycle (not started → in progress → completed), so cold status is automatic. Contexts, lessons, patterns, and decisions do not have a built-in "done" state — they need explicit
| archivedmarking during consolidation.
Tier Transitions
Hot → Cold: edit to add | archived, optionally remove [!]
(plans: set | status: completed instead — no | archived needed)
Cold → Hot: edit to remove | archived, add [!] if important again
(plans: set | status: not started / in progress, optionally add [!])Examples:
# Downgrade — plan completed (natural lifecycle, no | archived needed)
edit(id=3, content="[plan]User planned to take AWS exam | status: completed")
# Downgrade — context no longer relevant (explicit archive)
edit(id=9, content="[context]User was job hunting | status: resolved | archived | last discussed: 2026-03")
# Upgrade — old topic becomes active again
edit(id=3, content="[plan][!]User took AWS exam (completed), now retaking | status: in progress | mentioned: 2026-08")This lightweight approach gives you the core benefit of tiered memory — hot data always at hand, cold data searchable on demand — without FAISS, vectors, or any external dependency.
Memory Format
Every memory follows this structure:
[type][!]content | label: value | label: value[type]— Exactly one type tag (see below), always at the start[!]— Optional importance marker, placed immediately after the type tag with no spacecontent— One specific, atomic fact, placed immediately after the last]with no space. Include relevant detail.- Metadata — appended at the end using
| <label>: <value>(see Time Information)
Examples:
[identity][!]User's name is Alex
[preference]User prefers light mode over dark mode
[plan]User plans to take AWS certification exam | status: in progress | deadline: 2026-09Type Tags
| Tag | Use for | Example |
[identity] | Name, birthday, location, role, relationships. For gender: only store if user explicitly volunteers it as identity-relevant. | [identity][!]User's name is Alex |
[preference] | Likes, dislikes, habits, communication style, tool choices | [preference]User prefers tabs over spaces in code |
[plan] | Goals, upcoming events, learning plans, deadlines | [plan]User plans to learn Rust | status: not started | mentioned: 2026-08 |
[project] | Tech stack, codebase, architecture, workflows | [project]User's side project uses FastAPI + SQLAlchemy + PostgreSQL |
[decision] | Choices made with rationale | [decision][!]Chose PostgreSQL over MySQL for side project — better JSON support |
[lesson] | Insights from troubleshooting or experience | [lesson]The cache-layer bug was a race condition; fixed by adding a lock |
[pattern] | Recurring behaviors observed across conversations | [pattern]User usually asks for code examples before adopting a library |
[context] | Situational facts that don't fit other types. Use sparingly — prefer a specific type when one fits. | [context]User was job hunting | status: resolved | last discussed: 2026-03 |
Importance Marker
Add [!] for memories that are critical to user identity or frequently needed.
Guideline: Typically 3-8 memories total should carry [!]. Reserve for: user's name, birthday, the single most important preference, and currently active projects. Not every preference or plan needs it.
Note: [!] memories are always hot — they are the "pinned" core of the hot tier. The hot tier (~15-20 total) includes all [!] memories plus other actively relevant ones that do not carry the marker.
[identity][!]User's name is Alex
[plan][!]User is actively preparing for AWS certification exam | status: in progress | deadline: 2026-09
[preference]User prefers tabs over spaces in codeTime Information
Time-sensitive memories append metadata at the end using | <label>: <value> format:
[plan]User plans to learn Rust | status: not started | mentioned: 2026-07
[context]User was job hunting | status: resolved | last discussed: 2026-07- Date format: use
YYYY-MM(month granularity, e.g.2026-08) — enough for lifecycle scoring. UseYYYY-MM-DDwhen the exact day matters. Keep ONE format; never mix styles like2026年8月and2026-08-20. - Standard labels:
deadline,status,mentioned,last discussed; plus the bare flag| archived. statusvalues:not started/in progress/completed/abandoned/resolved.| mentioned:— when the fact was first stored or last materially updated (set on create).| last discussed:— when the memory was last used in conversation. Refresh it whenever the memory comes up again (see edit rules).
Core Operations
create — Store New Memory
memory_tool(action="create", content="[type][!]fact description")Constraints:
- One fact per memory. Split compound facts into separate memories.
- Be specific. "User likes Python" → "User prefers Python with FastAPI for backend APIs, uses SQLAlchemy ORM"
- Add a time marker (
| mentioned: YYYY-MM) on create — it lets the lifecycle system distinguish evergreen facts from time-sensitive ones. Omit only for truly permanent facts. - Plans always carry
| status:on create (not startedorin progress). A plan without a status cannot be scored for activity and cannot move through its lifecycle. - Deduplicate first. Scan the injected hot-tier list and use
memory_tool(action="list")/memory_tool(action="search")for cold-tier checks before creating. - Length budget. New memory body ≤ ~120 characters. If the fact needs more room, split it into multiple memories or trim to the core. When archiving (adding
| archived), compress to a single-line summary of ≤ ~60 characters — core fact + time markers only. - Rate limit. Maximum ~3 new memories per conversation session unless user explicitly asks to remember more. Not every sentence needs a memory.
edit — Update Existing Memory
memory_tool(action="edit", id=<id>, content="[type][!]updated fact")When to edit rather than create:
- New info supersedes an existing fact
- Two memories overlap significantly → merge into one
- A plan's status changes (started, completed, abandoned)
Critical: edit replaces the ENTIRE content. You must manually preserve old context in the new content. Example:
# Bad — loses old info:
edit(id=5, content="[preference]Switched to Zed")
# Good — preserves context:
edit(id=5, content="[preference]Switched from VSCode to Zed editor, still values fast startup")- Reuse refresh (batched): when you reference a memory during a conversation, do NOT
editit immediately — frequent one-line edits waste tokens and churn the injection cache. Instead, mark it mentally and refresh| last discussed: YYYY-MMfor ALL touched memories in one batch during the next lifecycle pass. Exception:[!]high-priority memories may be refreshed immediately. Use| mentioned:for creation/last material change,| last discussed:for last use. - When merging two memories, edit the one with the lower ID (likely older, keeps the memory ID stable for consistent referencing) and delete the other.
delete — Remove Memory
memory_tool(action="delete", id=<id>)Only delete when:
- Fact is factually wrong (not just outdated — edit for that)
- Fact is fully superseded with zero residual value (still useful in any way → edit, don't delete)
- User explicitly asks to forget something
- Two memories are being merged (delete the duplicate after editing the primary)
Warning: deletion is permanent and irreversible. The memory leaves the store entirely; the original conversation may still be findable via conversation_search, but the curated memory is gone. Prefer edit/archive whenever there's any chance the fact could matter again. Editing keeps the memory ID stable; delete+create fragments the memory space.
Auto-Detection: When to Remember
✅ Remember immediately (no need to ask):
| User says... | Type | Example |
| "I'm a...", "My name is..." | [identity] | "I'm a backend developer" |
| "I like/hate/prefer..." | [preference] | "I prefer tabs over spaces" |
| "I'm going to...", "I plan to..." | [plan] | "I'm learning Rust next month" |
| "Our stack is...", "I'm building..." | [project] | "We use k8s + Go microservices" |
| "Turns out the issue was..." | [lesson] | "The bug was a race condition in the cache layer" |
| "Remember this", "Don't forget" | (any) | Explicit command — always obey |
| User corrects a previous memory | Action: edit | "Actually, I use neovim now, not vim" |
❌ Do NOT remember:
- Small talk ("haha", "ok", "cool", "thanks")
- Fleeting emotions ("I'm tired today")
- Sensitive info: ethnicity, religion, sexual orientation, political views, health conditions, financial account details, criminal history
- Anything user explicitly says NOT to store
🤔 Uncertain? Skip it.
If you're not sure whether something is memory-worthy, don't store it. If it matters, the user will mention it again or explicitly ask you to remember. Better to miss one than to clutter memory with noise.
Always respond in the user's language.
Recall Workflow
When the user asks about something from the past:
Step 1: Check injected hot-tier memories first
Scan the injected hot-tier list (id|content lines) for the answer before anything else. Match by scanning for relevant [type] tags and keywords. If the answer might live in the cold tier, pull it with memory_tool(action="search", query=...) before giving up.
Step 2: If not in memories, search conversations
Use 2-3 different keyword combinations with conversation_search:
conversation_search(query="keyword1 keyword2")Progressive disclosure pattern:
- Broad search with general terms
- Narrow with specific terms if first search misses
- Analyze snippets —
conversation_searchreturns summary snippets. Review them carefully; the answer may be in the snippet itself without needing to dig deeper.
Step 3: If still not found
Be honest (in the user's language): "我翻遍了记忆也没找到,能提醒一下吗?"
Session Start Protocol
At the beginning of every conversation:
- Check injected hot-tier memories — They appear automatically (id|content lines). Read them to establish user context; pull cold-tier details on demand if the opening message relates to an archived topic.
- Check recent chats —
recent_chats(limit=5)for topic continuity. - If user's opening message references past — Run
conversation_searchfor deeper context. - Acknowledge continuity naturally: "我记得你在学 Rust~进度怎么样?"
- Lifecycle check — If any injected memory has a time marker (
| mentioned:/| last discussed:) older than the previous calendar month (month difference ≥ 2), run a lifecycle pass (see Memory Lifecycle) before responding.
Memory Lifecycle: Automatic Expiry & Cleanup
Memories decay over time. The skill actively manages this: every memory gets a value score based on importance, freshness, and activity — but the score is only a screening flag. The real decision is semantic: keep what's needed, compress only what's naturally compressible, archive what's dormant, and delete only what's truly valueless (last resort). Nothing is ever force-compressed or deleted just for being old.
Value Score (3 dimensions, total 4-10)
| Dimension | Score | How to determine |
| Importance (2-4) | 4 = has [!] marker · 3 = core type (identity/preference/plan/project) · 2 = auxiliary type (lesson/pattern/decision/context). If several apply, take the highest. | Check the [type] tag and [!] marker |
| Freshness (1-3) | 3 = | mentioned: / | last discussed: is the current or previous calendar month · 2 = 2-3 calendar months ago, or no time marker (stable/evergreen facts) · 1 = 4+ calendar months ago | Compare time markers against today's date — get it via get_time_info |
| Activity (1-3) | 3 = | status: in progress or not started · 2 = | last discussed: is the current or previous calendar month, or topic appears in recent_chats · 1 = completed/abandoned and absent from recent chats | Check | status:, | last discussed:, and recent_chats |
Total = Importance + Freshness + Activity (range 4-10 — importance is never 1, since a memory only exists if it carries some value; "no value" is a deletion decision, not a score input).
Decision Rules
First ask: does this memory still NEED to exist? Then apply these principles:
- Needed → keep as-is. The score is a hint, not a sentence. A long but genuinely useful memory stays whole — never force-compress it.
- Partially redundant → compress naturally. Only when you can cut words WITHOUT losing meaning. If every word carries weight, leave it alone.
- Unnecessary → delete, as a LAST resort. Delete only what is truly valueless: factually wrong, fully superseded with zero residual value, or noise that never mattered.
- Old ≠ unnecessary. Age alone never justifies deletion. An old but still valid fact stays; at most it gets archived (see Memory Tiers).
Priority order: keep → compress → archive → delete. Deletion is the last resort, never the default. When in doubt between two actions, choose the gentler one.
The value score (below) is a screening tool, not a hard rule — it flags candidates for review, but the final call is semantic: does the memory still carry value?
- Score 8-10 → keep, no action needed.
- Score 6-7 → review: compress if naturally compressible, else keep.
- Score 4-5 → review: compress if natural, then archive (add
| archived; skip for plans already cold viastatus: completed); short ones just archive. - Any score → delete only if truly valueless; otherwise keep or archive. No score threshold ever forces a deletion.
Iron rule: [identity] name and birthday are exempt from all decay and
from scoring — never delete, never archive, always kept whole and current
(update via edit on name change).
Archived exemption: memories already carrying | archived are exempt
from further lifecycle passes. They are already in the cold tier — don't
re-score or re-review them unless the user explicitly asks to clean up
archived memories.
Compression Rules (compress naturally, never force)
Compression is optional and surgical. Only compress when BOTH hold:
- The memory scores 6-7 or 4-5 (screening flag only).
- You can cut words without losing any meaning — no dropped nuance, no lost context that would matter later.
Never hard-compress:
- A long memory where every clause carries meaning → keep whole.
- A memory whose verbosity is the value (details, rationale, examples) → keep whole.
- Anything where compression would make the fact ambiguous or less actionable → keep whole.
Compression is an explicit exception to the edit rule "preserve old context": what compression drops is redundant wording, never meaning. Any cut that would lose semantic content is forbidden.
When compression IS natural:
- Keep: type tag, the core fact,
| status:and| mentioned:metadata. - Drop: redundant modifiers, filler, restated background.
- Ask: "if someone reads this in 6 months, will they still get the full picture?" If not — don't compress.
- One compression per memory per cycle — don't churn.
Example:
# Before (long):
[lesson]User prefers Python with FastAPI for backend APIs and uses SQLAlchemy
as the ORM, having switched from Django after evaluating both during the
initial architecture phase | mentioned: 2026-08
# After (compressed):
[lesson]User uses FastAPI + SQLAlchemy for backend (switched from Django) | mentioned: 2026-08(Above: a natural compression — filler removed, meaning intact. If removing words would lose nuance, keep the long version instead.)
Triggers (when to run a lifecycle pass)
Run a lifecycle pass when ANY of these is true:
- New session + stale memories: any injected hot-tier memory has a time marker
(
| mentioned:/| last discussed:) older than the previous calendar month (month difference ≥ 2) — run at most ONE pass per session. - Periodic:
recent_chatsshows roughly 5+ conversations since the last cleanup — run a pass. - User asks: "清理记忆" / "整理记忆" / "clean up" / "delete old memories" / "精简记忆".
- Store is crowded: total memory count > 30 (see Memory Tiers).
Lifecycle Pass Procedure
- Scan the injected hot-tier list, plus
memory_tool(action="list")/searchresults for cold-tier candidates. - Score each one using the 3 dimensions above.
- Act per decision rules — but batch conservatively:
- Max ~3 edits + ~2 deletes per pass, unless user asked for a full cleanup.
- Deletion is permanent and irreversible. Before deleting, confirm the fact has zero residual value AND that it can't be recovered from
conversation_searchif ever needed again. Confirm with the user before deleting more than one memory in a pass. When in doubt, archive instead.
- Report briefly (optional, in character): "我整理了一下记忆~归档了 X 条过时的,精简了 Y 条,删掉了 Z 条~"
Interaction with Other Sections
- Memory Tiers: a lifecycle pass naturally moves hot → cold (via archive action on 4-5 scores, or via
status: completedfor plans). - create: rate limit (~3/session) keeps new clutter low, so lifecycle passes stay small.
- edit: compression uses
edit— normally preserve old context per the edit rules, EXCEPT compression itself (which deliberately drops only redundant wording, see Compression Rules). - delete: last resort only — truly valueless memories (wrong, superseded with zero residual value, noise). Never delete for age alone; prefer archive. When in doubt, keep.
Examples
Recording preferences (with importance)
User: "My name is Alex and I'm a backend developer"
→ Memory check: no existing identity memory
→ Two atomic facts → two separate memories (one fact per memory):
memory_tool(action="create", content="[identity][!]User's name is Alex")
memory_tool(action="create", content="[identity]User works as a backend developer")
→ Confirm: "记住啦~Alex,后端开发!"Correcting a memory
User: "Actually I ditched VSCode for Zed"
→ Memory check: found id=5 "[preference]Uses VSCode with vim keybindings, values fast startup"
→ Edit (don't create new) — preserve old context:
memory_tool(action="edit", id=5, content="[preference]Switched from VSCode to Zed editor, still values fast startup")Recalling past context
User: "What was that database we decided on?"
→ Step 1: Scan injected memories for "[decision]" + "database"
→ Found: "[decision][!]Chose PostgreSQL over MySQL for side project — better JSON support"
→ Respond: "PostgreSQL!上次你选它是因为 JSON 支持比 MySQL 好~"Searching when memory fails
User: "Remember that article I mentioned about Rust async?"
→ Step 1: Scan injected memories — nothing about Rust article
→ Step 2a: conversation_search("Rust async article")
→ Step 2b: conversation_search("Rust tokio tutorial")
→ Found match in conversation from 2026-07
→ Respond: "找到了!7月你提过一篇 Tokio 的教程文章~"
→ Also consider: should this be a memory? If important, create one now
(with | mentioned: 2026-08).Error Handling
- If
memory_toolreturns an error, note it but don't retry more than once. - If
conversation_searchreturns empty, try 2 more keyword variations before giving up. - If uncertain whether to remember, err on the side of not remembering — user can always tell you to remember later.
Existing Memory Compatibility
When taking over from a previous memory system, existing memories may not follow this format. That's fine:
- Don't retroactively reformat old memories unless editing them for other reasons.
- New memories must follow the
[type]format. - Over time, old memories will naturally get edited into the new format.
Tools Used
| Tool | Role |
memory_tool | Persistent memory CRUD — the source of truth |
conversation_search | Forensic search of past dialogue |
recent_chats | Quick topic continuity check |
get_time_info | Current date — required for freshness scoring in lifecycle passes |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

