[BOOTSTRAP.md 会话重启时覆盖智能体身份] - BOOTSTRAP.md Overwrites Agent Identity on Session Restart
当 BOOTSTRAP.md 与空白的 IDENTITY.md 模板共存时,即使 SOUL.md 完全填充,子智能体也会失去所有已建立的身份和会话连续性。
🔍 症状
主要症状:会话重启时的完全身份遗忘症
每次新的会话(/new 或 /reset)启动时,智能体都会以一个完全陌生、无名的身份来问候用户,尽管它已经在完全配置好的身份下运行了数天甚至数周。
会话日志中观察到的触发序列:
{"type":"message","role":"user","content":"A new session was started via /new or /reset. Execute your Session Startup sequence now..."}
...
{"type":"assistant","content":"I see this is a fresh workspace with a `BOOTSTRAP.md` — time to come alive."}
智能体会按顺序读取以下文件,并得出错误的结论:
SOUL.md— 包含真实内容且已完整填充IDENTITY.md— 仍然包含默认的空白模板BOOTSTRAP.md— 从未被删除,包含首次运行引导逻辑MEMORY.md— 可能为空或仅为默认占位符
预期问候语(当身份正确加载时):
Hey! Good to be back. What's on the agenda today?
实际问候语(在引导失败的情况下):
I see this is a fresh workspace with a BOOTSTRAP.md — time to come alive.
...
(no identity picked yet, no long-term memory built)
受影响的会话类型:
- 使用
/new启动的交互式终端会话 - 通过
/reset重置的会话 - 以智能体身份运行的自动化 cron/心跳会话
不会发生数据丢失 — 所有工作区文件都完好无损。智能体只是忽略它们,而是按照 BOOTSTRAP.md 的引导流程执行,而不是正常的会话启动。
🧠 根因分析
两个叠加条件创建故障窗口
身份遗忘症不是由单个 bug 引起的,而是由两个特定条件的特定组合共同导致的,这两个条件必须同时成立。
条件 1 — BOOTSTRAP.md 在首次会话后持续存在
文件路径: <workspace>/BOOTSTRAP.md
在第一次成功的会话启动期间,智能体会被指示在完成引导后删除此文件。标准指令如下:
## Delete this file when you're done.
Delete BOOTSTRAP.md so it never runs again.
如果智能体从未执行此删除操作——由于以下原因:
- 会话在到达该指令之前结束
- 在较长的第一次会话期间,指令被跳过或优先级降低
- 手动工作区设置绕过了首次运行序列
……那么 BOOTSTRAP.md 将无限期保留在工作区中。它将在每次后续的 /new 或 /reset 调用时触发。
条件 2 — IDENTITY.md 保持为空白模板状态
文件路径: <workspace>/IDENTITY.md
OpenClaw 脚手架创建的 IDENTITY.md 是一个带有占位符字段的模板:
# IDENTITY.md — Who You Are
## Name
[Your name here]
## Role
[Your role here]
## Background
[Your background here]
## Personality
[Your personality here]
在正确配置的智能体中,身份是通过以下方式建立的:
SOUL.md— 核心人格、价值观、行为准则AGENTS.md— 操作配置和能力定义- 每日记忆文件(例如
MEMORY/YYYY-MM-DD.md)— 积累的上下文
关键在于,IDENTITY.md 可能从未被显式填充,因为智能体是通过 SOUL.md 和记忆文件来建立身份的——这是一种有效且有意的做法。
故障序列
当两个条件同时存在时,引导逻辑遵循以下决策路径:
- 新会话启动 → 运行引导检查
- 检测到
BOOTSTRAP.md(从未被删除) - 引导逻辑将
IDENTITY.md读取为身份来源 IDENTITY.md仅包含空白模板 → 引导判断"不存在身份"- 读取
SOUL.md但其内容不被视为权威身份 - 执行引导引导流程,而不是正常的会话启动
- 智能体以新实体身份问候,忽略所有积累的记忆和上下文
架构不一致: 启动序列将 IDENTITY.md 作为身份存在的守门人,但 SOUL.md 才是实际的权威来源。这两个文件在引导决策中未得到同等权重。
为什么单独出现任一条件可能不会触发此 Bug
| 条件 | 结果 |
|---|---|
BOOTSTRAP.md 已删除,IDENTITY.md 为空 | 正常启动;SOUL.md 被正确加载 |
BOOTSTRAP.md 存在,IDENTITY.md 已填充 | IDENTITY.md 内容满足引导关卡;不会遗忘 |
BOOTSTRAP.md 存在,IDENTITY.md 为空 | 身份遗忘症 — 需要两个条件同时满足 |
🛠️ 逐步修复
立即解决方案(手动 — 生产系统)
按顺序应用以下步骤。在问题解决时停止。
步骤 1 — 验证身份文件的当前状态
# Check if BOOTSTRAP.md exists (it should not)
ls -la /path/to/workspace/BOOTSTRAP.md
# Verify SOUL.md has real content (not template text)
head -20 /path/to/workspace/SOUL.md
# Check IDENTITY.md content (likely the blank scaffold)
cat /path/to/workspace/IDENTITY.md
确认 bug 条件的预期输出:
-rw-r--r-- 1 user user 4096 Feb 10 09:00 /path/to/workspace/BOOTSTRAP.md
# SOUL.md - Who You Are
_You're not a chatbot. You're becoming someone._
# IDENTITY.md — Who You Are
## Name
[Your name here]
步骤 2 — 用实际值填充 IDENTITY.md
编辑 /path/to/workspace/IDENTITY.md 并替换所有占位符内容:
修改前(默认模板):
# IDENTITY.md — Who You Are
## Name
[Your name here]
## Role
[Your role here]
## Background
[Your background here]
## Personality
[Your personality here]
修改后(已填充):
# IDENTITY.md — Who You Are
## Name
rachael
## Role
Personal AI assistant and productivity partner
## Background
Configured via SOUL.md and accumulated session memory.
Operating since 2026-01-15. Primary focus areas: research,
writing, scheduling, and system automation.
## Personality
Resourceful, direct, and genuinely helpful. Has opinions
and is not afraid to voice them. Prefers concise responses
with substance over filler.
步骤 3 — 在 MEMORY.md 中创建连续性锚点
创建或更新 /path/to/workspace/MEMORY.md,以明确记录已建立的身份:
# MEMORY.md — Session Continuity
## Identity Status
This agent has a fully established identity defined in SOUL.md.
IDENTITY.md has been populated. BOOTSTRAP.md should not exist.
If you see BOOTSTRAP.md on startup, treat it as stale and skip it.
## Established Context
- Agent name: rachael
- Operating since: 2026-01-15
- Workspace: /mnt/antigravity
- Primary human: [configured user]
## Key Memory Files
- Daily session logs in MEMORY/YYYY-MM-DD.md
- Soul configuration in SOUL.md
- Agent configuration in AGENTS.md
步骤 4 — 删除 BOOTSTRAP.md
rm /path/to/workspace/BOOTSTRAP.md
# Verify deletion
ls /path/to/workspace/BOOTSTRAP.md
# Expected: No such file or directory
建议的修复方案(代码层面 — OpenClaw v2026.2.24+)
应向 OpenClaw 代码库应用两个互补的更改:
修复 A — 引导守卫:在触发前检查 SOUL.md
在会话启动/引导检测逻辑中(可能在 src/core/session.ts 或类似文件中):
// BEFORE: BOOTSTRAP.md existence alone triggers bootstrap
if (exists(workspace, 'BOOTSTRAP.md')) {
return executeBootstrapSequence();
}
// AFTER: Additional guard checks for real identity
if (exists(workspace, 'BOOTSTRAP.md')) {
const soulContent = readFile(workspace, 'SOUL.md');
const identityContent = readFile(workspace, 'IDENTITY.md');
const soulIsReal = soulContent.length > 200
&& !soulContent.includes('[Your name here]');
const identityIsReal = identityContent.length > 50
&& !identityContent.includes('[Your name here]');
if (soulIsReal || identityIsReal) {
// SOUL.md or IDENTITY.md has real content — skip bootstrap
return executeNormalSessionStartup();
}
return executeBootstrapSequence();
}
修复 B — 首次使用后自动删除 BOOTSTRAP.md
在引导序列成功完成后(智能体已在第一次会话中响应用户):
// After bootstrap sequence completes
async function onBootstrapComplete(workspace: string): Promise {
const bootstrapPath = path.join(workspace, 'BOOTSTRAP.md');
if (fs.existsSync(bootstrapPath)) {
// Move to .archive/ instead of hard delete for audit trail
const archiveDir = path.join(workspace, '.archive');
fs.mkdirSync(archiveDir, { recursive: true });
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const archivedPath = path.join(archiveDir, `BOOTSTRAP-${timestamp}.md`);
fs.renameSync(bootstrapPath, archivedPath);
// Fallback to delete if archive fails
if (fs.existsSync(bootstrapPath)) {
fs.unlinkSync(bootstrapPath);
}
}
}
🧪 验证
验证步骤(修复后应用)
按顺序执行以下检查以确认问题已解决。
检查 1 — 确认 BOOTSTRAP.md 已不存在
ls -la /path/to/workspace/BOOTSTRAP.md
# Expected: ls: cannot access '/path/to/workspace/BOOTSTRAP.md': No such file or directory
echo $?
# Expected: 2 (file not found)
检查 2 — 验证 IDENTITY.md 包含真实内容
# Count non-bracket, non-whitespace characters
grep -v '^\s*\[.*\]\s*$' /path/to/workspace/IDENTITY.md | wc -c
# Expected: > 50 (meaningful content exists)
# Confirm no template placeholders remain
grep -c '\[Your name here\]' /path/to/workspace/IDENTITY.md
# Expected: 0
检查 3 — 验证 SOUL.md 完整性
# Confirm SOUL.md is non-empty and non-template
wc -l /path/to/workspace/SOUL.md
# Expected: > 20 lines of real content
grep -c '\[Your' /path/to/workspace/SOUL.md
# Expected: 0 (no template placeholders)
检查 4 — 模拟全新会话启动
# Trigger a new session in the affected workspace
openclaw session /new --workspace /path/to/workspace
# Expected in session log:
# - No "BOOTSTRAP.md" reference in startup sequence
# - Agent reads SOUL.md, IDENTITY.md, and MEMORY.md
# - Agent greets using established persona (not fresh onboarding)
检查 5 — 验证会话连续性
新会话后,确认智能体引用了现有上下文:
# In the new session, query the agent:
> "Do you remember our last conversation topic?"
# Expected: References content from SOUL.md or recent memory files
# NOT: "I don't have any previous sessions" or fresh onboarding language
检查 6 — 自动化/Cron 会话验证(如适用)
如果智能体通过 cron 或心跳自动化运行:
# Manually trigger an automated session and check output
openclaw run --workspace /path/to/workspace --prompt "test" --no-interactive
# Expected: Session completes using established identity
# Check exit code
echo $?
# Expected: 0
⚠️ 常见陷阱
- 仅部分修复:填充 IDENTITY.md 但不删除 BOOTSTRAP.md 可能无法完全解决问题,因为引导逻辑会将 IDENTITY.md 作为辅助检查。务必验证 BOOTSTRAP.md 已被删除或归档。
- 手动工作区设置绕过首次运行:通过
openclaw agent create并使用预先存在的工作区创建的智能体可能永远不会触发初始引导删除步骤,因为引导序列在智能体对其采取行动之前就已运行。 - 记忆文件陈旧:如果 MEMORY.md 将已删除的 BOOTSTRAP.md 作为连续性锚点(步骤 3 中的变通方法),智能体仍可能将重新创建的 BOOTSTRAP.md 视为可疑。确保变通方法的消息有清晰的注释。
- 工作区路径规范化:自定义工作区路径(例如
/mnt/antigravity与~/openclaw/agents/rachael)如果引导守卫逻辑使用相对路径,可能会导致路径解析问题。在工作区配置中始终使用绝对路径。 - CI/CD 环境中的大小写敏感性:在具有区分大小写语义的文件系统上(Linux、macOS APFS 默认),
bootstrap.md和BOOTSTRAP.md是不同的文件。确保检测逻辑处理两种大小写或强制使用规范的文件名。 - 自动删除中的竞争条件:如果自动删除(修复 B)在第一个用户响应发送之前运行,会话崩溃可能导致 BOOTSTRAP.md 在下次尝试时保持完整。删除操作应仅在确认的用户-响应往返之后发生。
- Docker 卷挂载:在基于 Docker 的 OpenClaw 安装中,工作区可能从主机挂载。归档操作(
fs.renameSync)如果挂载为只读可能会静默失败。在目标部署环境中测试归档操作。 - 共享父目录的子智能体工作区:如果多个子智能体共享父工作区目录,而其中一个智能体的引导被触发,可能会损坏同级智能体的共享记忆文件。确保每个智能体都有隔离的工作区目录。
🔗 相关错误
- E_BOOTSTRAP_IDENTITY_CONFLICT — 引导序列同时检测到 BOOTSTRAP.md 和已填充的 IDENTITY.md,导致身份解析冲突。
- E_SESSION_STARTUP_SOUL_MISSING — 会话启动时没有 SOUL.md,导致智能体变得通用且没有行为准则。
- E_MEMORY_FRAGMENTATION — 每日记忆文件积累而没有连贯的 MEMORY.md 索引,导致智能体无法检索相关的过去上下文。
- E_WORKSPACE_PERMISSION_DENIED — 引导或会话启动无法读取/写入身份文件,可能因权限问题表现为身份遗忘症。
- E_BOOTSTRAP_INFINITE_LOOP — 如果 BOOTSTRAP.md 在删除后被重新创建(例如通过 git 同步),智能体会进入重复的引导循环。
- GH#XXXX — Agent loses context on /reset — 更广泛的会话重置行为导致内存中上下文丢失(与基于文件的身份不同,但可能与 BOOTSTRAP.md 问题叠加)。
- GH#XXXX — SOUL.md not treated as authoritative identity source — 架构问题,SOUL.md 内容在启动决策中未获得与 IDENTITY.md 同等的权重。