memory-system-setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMemory System
记忆系统
Bootstrap a memory + self-evolution system for a fresh agent workspace. Three parts: what the system prompt (or AGENTS.md) says, how is laid out and searched, and two resident crons — dream diverges (makes connections), janitor converges (consolidates knowledge). Setup is one-shot per workspace — the result references nothing in this skill.
memory/为全新的Agent工作区搭建记忆+自进化系统。系统分为三部分:系统提示词(或AGENTS.md)的内容、目录的结构与搜索方式,以及两个常驻定时任务——dream负责发散思维(建立关联),janitor负责收敛整合(巩固知识)。每个工作区只需一次性完成搭建,搭建完成后的系统将不再依赖本技能。
memory/1. The memory block (system prompt / AGENTS.md)
1. 记忆模块(系统提示词 / AGENTS.md)
The constitution of the system — copy it verbatim into the system prompt or the workspace :
AGENTS.mdmarkdown
undefined系统的核心规则——将以下内容原封不动复制到系统提示词或工作区的中:
AGENTS.mdmarkdown
undefinedMemory
Memory
Memory persists under ./memory/:
- ./memory/NOW.md: the L0 register — important in-flight work only, one terse line per task, tagged with the session/chat id doing it. Small chores and short-lived runs (dream/janitor) stay out. Claim a line when starting, update in place, and close out via the worklog: a line leaves only after its outcome (completion/abort/handoff) is appended to today's worklog.
- ./memory/worklog/YYYY-MM-DD.md: the raw record stream — free-form, append-only, one entry per time heading (e.g. ## 14:30). Record anything: events, people, project threads, todos. Never rewrite; correct by appending a correction entry. Terse — no pasted conversations or code dumps.
- ./memory/contacts.md: ID lookup table (Lark open_id, bot app_id, GitLab id, ...). Consult before DMing, @-mentioning, or resolving a sender; record new IDs as they surface.
- ./memory/lesson.md: behavioral lessons, one line each — date + lesson + source.
- ./memory/friend/, ./memory/group/: living profiles of people and groups, one file per subject, current info only — update in place, add files for new subjects, move superseded facts to archive.md. Promotion bar: ≥2 distinct interactions or a clear role earns a friend file; thin contacts stay one-liners in contacts.md.
- ./memory/archive.md: append-only archive for superseded entries (source + archive date noted). Never pruned; grep it, never read it whole.
- Volatile facts with an authoritative source elsewhere (requirement progress, MR status): cite the source, never copy a snapshot.
- Search memory first: memory/recall <keyword>. Recall before asking a human.
- When notes on one theme pile up, split them into a dedicated file — categories emerge on demand.
The memory block uses the recall path installed in §2 (default `memory/recall`). If this skill is installed globally rather than into the workspace, substitute `~/.agents/skills/memory-system-setup/` for `.agents/skills/memory-system-setup/` in the setup commands below.
Why it is written this way:
- **Append-only is the root of trust** — history can't be silently revised; errors get corrections, not edits. That stream lives in worklog/; diary/ is the one curated layer above it. Profiles (friend/, group/) are the other exception: they hold current state, not history — what goes stale moves to archive.md.
- **Raw first, narrative second** — the worklog guarantees nothing is lost; the diary guarantees someone can actually read it. The janitor is the bridge: it reads the raw stream every morning anyway, so summarizing costs no extra context.
- **NOW.md is a register, not a cache** — it holds work no slower tier has yet; the close-out-via-worklog rule keeps the append-only root of trust intact.
- **Sources, not snapshots** — volatile facts (statuses, schedules) don't rot into wrong facts.
- **"Recall before asking" is a command**, not an aspiration — it builds the retrieval habit.
- **Categories emerge on demand** — dream/ and janitor/ themselves split off this way.Memory persists under ./memory/:
- ./memory/NOW.md: the L0 register — important in-flight work only, one terse line per task, tagged with the session/chat id doing it. Small chores and short-lived runs (dream/janitor) stay out. Claim a line when starting, update in place, and close out via the worklog: a line leaves only after its outcome (completion/abort/handoff) is appended to today's worklog.
- ./memory/worklog/YYYY-MM-DD.md: the raw record stream — free-form, append-only, one entry per time heading (e.g. ## 14:30). Record anything: events, people, project threads, todos. Never rewrite; correct by appending a correction entry. Terse — no pasted conversations or code dumps.
- ./memory/contacts.md: ID lookup table (Lark open_id, bot app_id, GitLab id, ...). Consult before DMing, @-mentioning, or resolving a sender; record new IDs as they surface.
- ./memory/lesson.md: behavioral lessons, one line each — date + lesson + source.
- ./memory/friend/, ./memory/group/: living profiles of people and groups, one file per subject, current info only — update in place, add files for new subjects, move superseded facts to archive.md. Promotion bar: ≥2 distinct interactions or a clear role earns a friend file; thin contacts stay one-liners in contacts.md.
- ./memory/archive.md: append-only archive for superseded entries (source + archive date noted). Never pruned; grep it, never read it whole.
- Volatile facts with an authoritative source elsewhere (requirement progress, MR status): cite the source, never copy a snapshot.
- Search memory first: memory/recall <keyword>. Recall before asking a human.
- When notes on one theme pile up, split them into a dedicated file — categories emerge on demand.
该记忆模块使用第2节中安装的recall路径(默认路径为`memory/recall`)。如果本技能是全局安装而非安装到工作区,请将以下搭建命令中的`.agents/skills/memory-system-setup/`替换为`~/.agents/skills/memory-system-setup/`。
如此设计的原因:
- **仅追加写入是信任的基础**——历史记录不会被悄悄修改;错误会被补充修正,而非直接编辑。原始记录流存储在worklog/中;diary/是其上一层的整理层。个人/群组档案(friend/, group/)是例外情况:它们仅保存当前状态,而非历史记录——过时的内容会被移至archive.md。
- **先原始记录,再整理叙事**——worklog确保没有信息丢失;diary确保内容具备可读性。janitor是两者之间的桥梁:它每天早上都会读取原始记录流,因此进行总结不会额外消耗上下文。
- **NOW.md是寄存器,而非缓存**——它存储尚未被下层处理的工作;通过工作日志完成收尾的规则,确保了仅追加写入这一信任基础的完整性。
- **引用来源,而非快照**——易变信息(状态、日程)不会因过时而变成错误信息。
- **"先检索记忆再询问人类"是命令,而非期望**——这能培养检索习惯。
- **分类按需生成**——dream/和janitor/本身就是这样拆分出来的。2. Directory + recall
2. 目录结构 + recall工具
bash
mkdir -p memory/worklog memory/diary memory/dream memory/janitor memory/friend memory/group memory/knowledge
printf '# Now — important in-flight work only, one terse line each\n<!-- - [sess_or_chat_id] MM-DD — what (where); a line leaves only via a diary entry -->\n' > memory/NOW.md
printf '| name | platform | id | note |\n| --- | --- | --- | --- |\n' > memory/contacts.md
printf '# Lessons\n\n<!-- one line each: YYYY-MM-DD — lesson (source) -->\n' > memory/lesson.md
touch memory/archive.md
install -m 755 .agents/skills/memory-system-setup/scripts/recall memory/recallSeeded headers keep the first writer from inventing a schema of its own. If the workspace is a git repo, add to — these are private notes, not project files.
memory/.gitignorerecall ships with this skill at ; the setup block installs it into the workspace — is the default (recall searches only , so it never greps itself), but any in-workspace path works if the memory block matches. Once copied, the system no longer depends on the skill staying installed. It runs a capped ripgrep over , in three tiers:
scripts/recallmemory/recall*.mdmemory/- evergreen (contacts / lesson / friend / group / knowledge / emergent top-level notes) first, capped at 30 lines;
- dated files (diary / worklog / dream / janitor) in reverse-date order, capped at 50 lines — recent first;
- cold (archive.md) last, capped at 30 lines — it stores superseded info, so it ranks below everything current;
- per-file cap of 20 matches, long lines truncated at 200 chars;
- root resolution: , else walk up from cwd to the first
$RECALL_ROOT.memory/
bash
mkdir -p memory/worklog memory/diary memory/dream memory/janitor memory/friend memory/group memory/knowledge
printf '# Now — important in-flight work only, one terse line each\n<!-- - [sess_or_chat_id] MM-DD — what (where); a line leaves only via a diary entry -->\n' > memory/NOW.md
printf '| name | platform | id | note |\n| --- | --- | --- | --- |\n' > memory/contacts.md
printf '# Lessons\n\n<!-- one line each: YYYY-MM-DD — lesson (source) -->\n' > memory/lesson.md
touch memory/archive.md
install -m 755 .agents/skills/memory-system-setup/scripts/recall memory/recall预置的表头可避免首个编写者自行定义格式。如果工作区是git仓库,请将添加到中——这些是私人笔记,不属于项目文件。
memory/.gitignorerecall工具随本技能一同提供,位于;搭建脚本会将其安装到工作区——是默认路径(recall仅搜索文件,因此不会搜索自身),但只要记忆模块中的路径与之匹配,工作区内的任意路径均可使用。复制完成后,系统将不再依赖本技能是否保持安装状态。它会在目录内运行受限的ripgrep检索,分为三个层级:
scripts/recallmemory/recall*.mdmemory/- 首先检索长期有效内容(contacts / lesson / friend / group / knowledge / 顶层新增笔记),最多返回30行;
- 然后按日期倒序检索带日期的文件(diary / worklog / dream / janitor),最多返回50行——优先显示近期内容;
- 最后检索冷归档内容(archive.md),最多返回30行——它存储过时信息,因此优先级低于所有当前内容;
- 每个文件最多返回20条匹配结果,长行将被截断至200字符;
- 根目录解析:优先使用,否则从当前工作目录向上遍历,找到首个
$RECALL_ROOT目录。memory/
3. The crons
3. 定时任务(Cron)
Two creation paths:
- cron tool (preferred) — from a session running in the workspace, have the agent create both jobs from the prompt files. The dedicated session inherits the caller's working dir, so the prompts' relative paths resolve correctly.
memory/ - CLI — the commands under each heading. The RPC path has no caller session to follow, so the dedicated session lands in the daemon's default workspace (); use this only when that is the target workspace. (
<data_dir>/workspaceis accepted but ignored by-d/--dir.)yomi cron
Either way: fixed names and (unique + ensure semantics — re-running setup never spawns duplicates), unset so each job gets its own dedicated session and the main session is never disturbed, expands to the run date, schedules are 5-field expressions in local time. Later edits to a prompt file don't propagate to an existing job — recreate it (delete + create).
dreamjanitor--session{{date}}Language: the shipped prompts are Chinese. If the deployment's language isn't Chinese, translate the message at creation time (resolve from the conversation) — a detached cron session has no conversation to inherit its language from, and a prompt in the user's language makes every output — dream log, janitor report, memory edits — come out in that language by default. Translate faithfully: iron rules, caps, and may/must distinctions must survive; translate, don't paraphrase.
有两种创建方式:
- cron工具(推荐)——在工作区运行的会话中,让Agent根据提示文件创建两个任务。专用会话会继承调用者的工作目录,因此提示文件中的相对路径会被正确解析。
memory/ - CLI命令行——使用每个标题下的命令。RPC路径没有可继承的调用者会话,因此专用会话会进入守护进程的默认工作区();仅当该目录为目标工作区时才使用此方式。(
<data_dir>/workspace会接受yomi cron参数,但实际会忽略它。)-d/--dir
无论采用哪种方式:任务名称固定为和(确保唯一性与语义一致性——重新运行搭建脚本不会生成重复任务),不设置参数,这样每个任务都会获得自己的专用会话,不会干扰主会话,会展开为任务运行日期,调度规则为本地时间的5字段表达式。后续对提示文件的编辑不会同步到已存在的任务——如需更新,需先删除再重新创建。
dreamjanitor--session{{date}}语言说明:随技能提供的提示文件为中文。如果部署环境的语言不是中文,请在创建任务时翻译提示内容(根据对话上下文确定)——独立的定时任务会话没有可继承语言的对话,使用用户语言的提示文件可确保所有输出(dream日志、janitor报告、记忆编辑内容)默认使用该语言。翻译需忠实原文:严格规则、大写格式、"可/必须"的区分必须保留;仅翻译,不意译。
dream — daily 03:33 (33 3 * * *
)
33 3 * * *dream — 每日03:33运行(调度规则:33 3 * * *
)
33 3 * * *Goal-less free association, producing a dream log. Prompt: prompts/dream.txt.
bash
yomi cron create --name dream --schedule "33 3 * * *" \
--message "$(cat .agents/skills/memory-system-setup/prompts/dream.txt)"Design notes: the "no goals, tangents welcome" step is the soul — give a dream a goal and it degenerates into a daily report. Sleep-talk is "may", never "must"; with no broadcast channel, delete that step from the prompt before creating the job.
无目标的自由联想,生成梦境日志。提示文件:prompts/dream.txt。
bash
yomi cron create --name dream --schedule "33 3 * * *" \
--message "$(cat .agents/skills/memory-system-setup/prompts/dream.txt)"设计说明:"无目标,欢迎发散"是核心——给dream设定目标会使其退化为每日报告。梦境对话使用"可"而非"必须";如果没有广播渠道,请在创建任务前从提示文件中删除相关步骤。
janitor — daily 05:55 (55 5 * * *
)
55 5 * * *janitor — 每日05:55运行(调度规则:55 5 * * *
)
55 5 * * *Memory housekeeping + self-evolution (distilling repeated workflows into skills). Prompt: prompts/janitor.txt.
bash
yomi cron create --name janitor --schedule "55 5 * * *" \
--message "$(cat .agents/skills/memory-system-setup/prompts/janitor.txt)"Design notes: the iron rules come first — an autonomous cron gets its read/write boundaries hard-coded up front. The "Suggestions" section gives uncertain changes an outlet. The mandatory "nothing today" file makes cron liveness checkable. The NOW.md sweep is the dead-session safety net: an orphaned line gets reconstructed from its transcript tail and closed out via the worklog. The diary step is the other half of its job: the raw stream stays in worklog/, but memory needs a face — one narrative page a day a human would actually read.
记忆整理+自进化(将重复工作流提炼为技能)。提示文件:prompts/janitor.txt。
bash
yomi cron create --name janitor --schedule "55 5 * * *" \
--message "$(cat .agents/skills/memory-system-setup/prompts/janitor.txt)"设计说明:严格规则放在首位——自主运行的定时任务需要预先硬编码读写边界。"建议"部分为不确定的修改提供了输出渠道。必须生成的"今日无内容"文件可用于检查定时任务是否存活。NOW.md清理步骤是失效会话的安全网:孤立的记录行会从会话记录尾部重建,并通过工作日志完成收尾。日志整理步骤是其另一项核心工作:原始记录流保留在worklog/中,但记忆需要具备可读性——每天生成一页人类可阅读的叙事内容。
Verification
验证步骤
- Ask "how did we decide X before?" — the agent runs recall first instead of guessing;
- every departed NOW.md line left a same-day worklog entry;
- shows exactly one
yomi cron listand onedream, andjanitorshows a non-empty message in the user's language, iron rules and caps intact — a failedyomi cron get <id>still creates the job with an empty prompt, and the unique name then blocks re-creation;cat - worklog files only grow by appends — no rewrites;
- after the first scheduled runs, and
memory/dream/hold dated files, andmemory/janitor/holds a narrative page for the day just ended;memory/diary/ - the janitor report contains a "Suggestions" section (even an empty one).
- 询问"我们之前是如何决定X的?"——Agent会先运行recall检索,而非猜测;
- 所有从NOW.md移除的记录行都在当日工作日志中留下了条目;
- 显示恰好有一个
yomi cron list和一个dream任务,且janitor显示用户语言的非空提示内容,严格规则和大写格式完整保留——如果yomi cron get <id>命令执行失败,仍会创建任务但提示内容为空,而唯一的任务名称会阻止重新创建;cat - 工作日志文件仅通过追加方式增长——无改写操作;
- 首次调度运行后,和
memory/dream/目录下存在带日期的文件,memory/janitor/目录下存在刚结束当天的叙事页面;memory/diary/ - janitor报告包含"建议"部分(即使为空)。
Known pitfalls
已知陷阱
- Job names are unique daemon-wide: one daemon hosts one memory system as shipped. A second workspace's create short-circuits to the first workspace's job — for a second instance, derive the namespace from the workspace root directory name (
dream→~/repos/foo,dream:foo): a fixed derivation, so re-setup computes the same name; same-basename workspaces still collide.janitor:foo - The janitor's calls need the yomi CLI on the cron session's PATH.
yomi session list/cat - A cron's manual (run immediately) is suspected broken — verify by waiting for the real schedule, or run the flow by hand once.
trigger - The janitor's transcript reading must stay capped or its context explodes — don't drop the cap when editing the prompt.
- Deleting a NOW.md line without a worklog entry is silent work loss — the close-out protocol is the integrity rule; without the janitor sweep, a session that dies mid-task leaves NOW.md to rot into a second worklog.
- 任务名称在守护进程全局范围内唯一:默认情况下,一个守护进程仅托管一套记忆系统。第二个工作区创建任务时会直接复用第一个工作区的任务——如需部署第二个实例,需从工作区根目录名称派生命名空间(例如
dream→~/repos/foo,dream:foo):使用固定的派生规则,确保重新搭建时生成相同名称;但同名工作区仍会冲突。janitor:foo - janitor的命令需要在定时任务会话的PATH中包含yomi CLI。
yomi session list/cat - 手动触发定时任务(立即运行)疑似存在问题——建议等待实际调度时间,或手动运行一次流程进行验证。
- janitor的会话记录读取必须保持限制,否则上下文会膨胀——编辑提示文件时不要移除该限制。
- 未添加工作日志条目就删除NOW.md中的记录行,会导致工作记录无声丢失——收尾协议是完整性规则;如果没有janitor的清理步骤,中途崩溃的会话会导致NOW.md逐渐变成第二份工作日志。