memory-system-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Memory System

记忆系统

Bootstrap a memory + self-evolution system for a fresh agent workspace. Three parts: what the system prompt (or AGENTS.md) says, how
memory/
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.
为全新的Agent工作区搭建记忆+自进化系统。系统分为三部分:系统提示词(或AGENTS.md)的内容、
memory/
目录的结构与搜索方式,以及两个常驻定时任务——dream负责发散思维(建立关联),janitor负责收敛整合(巩固知识)。每个工作区只需一次性完成搭建,搭建完成后的系统将不再依赖本技能。

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.md
:
markdown
undefined
系统的核心规则——将以下内容原封不动复制到系统提示词或工作区的
AGENTS.md
中:
markdown
undefined

Memory

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/recall
Seeded headers keep the first writer from inventing a schema of its own. If the workspace is a git repo, add
memory/
to
.gitignore
— these are private notes, not project files.
recall ships with this skill at
scripts/recall
; the setup block installs it into the workspace —
memory/recall
is the default (recall searches only
*.md
, 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
memory/
, in three tiers:
  • 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:
    $RECALL_ROOT
    , else walk up from cwd to the first
    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/
添加到
.gitignore
中——这些是私人笔记,不属于项目文件。
recall工具随本技能一同提供,位于
scripts/recall
;搭建脚本会将其安装到工作区——
memory/recall
是默认路径(recall仅搜索
*.md
文件,因此不会搜索自身),但只要记忆模块中的路径与之匹配,工作区内的任意路径均可使用。复制完成后,系统将不再依赖本技能是否保持安装状态。它会在
memory/
目录内运行受限的ripgrep检索,分为三个层级:
  • 首先检索长期有效内容(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
    memory/
    paths resolve correctly.
  • 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 (
    <data_dir>/workspace
    ); use this only when that is the target workspace. (
    -d/--dir
    is accepted but ignored by
    yomi cron
    .)
Either way: fixed names
dream
and
janitor
(unique + ensure semantics — re-running setup never spawns duplicates),
--session
unset so each job gets its own dedicated session and the main session is never disturbed,
{{date}}
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).
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
    参数,但实际会忽略它。)
无论采用哪种方式:任务名称固定为
dream
janitor
(确保唯一性与语义一致性——重新运行搭建脚本不会生成重复任务),不设置
--session
参数,这样每个任务都会获得自己的专用会话,不会干扰主会话,
{{date}}
会展开为任务运行日期,调度规则为本地时间的5字段表达式。后续对提示文件的编辑不会同步到已存在的任务——如需更新,需先删除再重新创建。
语言说明:随技能提供的提示文件为中文。如果部署环境的语言不是中文,请在创建任务时翻译提示内容(根据对话上下文确定)——独立的定时任务会话没有可继承语言的对话,使用用户语言的提示文件可确保所有输出(dream日志、janitor报告、记忆编辑内容)默认使用该语言。翻译需忠实原文:严格规则、大写格式、"可/必须"的区分必须保留;仅翻译,不意译。

dream — daily 03:33 (
33 3 * * *
)

dream — 每日03:33运行(调度规则:
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 * * *
)

janitor — 每日05:55运行(调度规则:
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;
  • yomi cron list
    shows exactly one
    dream
    and one
    janitor
    , and
    yomi cron get <id>
    shows a non-empty message in the user's language, iron rules and caps intact — a failed
    cat
    still creates the job with an empty prompt, and the unique name then blocks re-creation;
  • worklog files only grow by appends — no rewrites;
  • after the first scheduled runs,
    memory/dream/
    and
    memory/janitor/
    hold dated files, and
    memory/diary/
    holds a narrative page for the day just ended;
  • 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
    dream
    create short-circuits to the first workspace's job — for a second instance, derive the namespace from the workspace root directory name (
    ~/repos/foo
    dream:foo
    ,
    janitor:foo
    ): a fixed derivation, so re-setup computes the same name; same-basename workspaces still collide.
  • The janitor's
    yomi session list/cat
    calls need the yomi CLI on the cron session's PATH.
  • A cron's manual
    trigger
    (run immediately) is suspected broken — verify by waiting for the real schedule, or run the flow by hand once.
  • 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的
    yomi session list/cat
    命令需要在定时任务会话的PATH中包含yomi CLI。
  • 手动触发定时任务(立即运行)疑似存在问题——建议等待实际调度时间,或手动运行一次流程进行验证。
  • janitor的会话记录读取必须保持限制,否则上下文会膨胀——编辑提示文件时不要移除该限制。
  • 未添加工作日志条目就删除NOW.md中的记录行,会导致工作记录无声丢失——收尾协议是完整性规则;如果没有janitor的清理步骤,中途崩溃的会话会导致NOW.md逐渐变成第二份工作日志。