三、龙虾分身
在 OpenClaw 里,一个 Agent 就是一个独立的 “龙虾分身”,每个分身都有专属的大脑(模型)、双手(工具 / Skill)、记忆库(独立工作区)和人设(IDENTITY.md),能自己干活、独立对话,多个分身还能分工协作。
一个 Agent 包含:
| 组成部分 | 说明 | 文件位置 |
|---|---|---|
| 工作区 | 龙虾的"家",存放人设、记忆、技能 | ~/.openclaw/workspace |
| 会话 | 对话记录,每个聊天窗口一个 | ~/.openclaw/agents/<id>/sessions/ |
| 认证 | API 密钥、OAuth 令牌 | ~/.openclaw/agents/<id>/agent/ |
| 配置 | 模型、工具、行为规则 | ~/.openclaw/openclaw.json |
Windows 用户:
~/在 Windows 上是C:\Users\你的用户名\,所以~/.openclaw/workspace就是C:\Users\你的用户名\.openclaw\workspace。
简单来说:一个 Agent = 一个独立的 AI 助手实例,有自己的记忆、性格和能力边界。默认情况下 OpenClaw 运行一个 Agent(id 为 main),但你也可以创建多个 Agent 来服务不同场景(后文详述)。
1. 首次启动:引导仪式
首次运行 Agent 时,OpenClaw 会执行一个引导仪式(Bootstrapping)——一个简短的问答过程,帮助龙虾了解"它是谁"和"你是谁"。
- 在工作区中创建
AGENTS.md、BOOTSTRAP.md、IDENTITY.md、USER.md - 运行一轮简短的问答(每次一个问题)
- 将你的回答写入
IDENTITY.md、USER.md、SOUL.md - 完成后自动删除
BOOTSTRAP.md(确保只运行一次)
**引导仪式始终在 Gateway 所在的机器上执行,如果安装时使用了快速模式的话会自动创建。
如果你已经自行管理工作区文件(比如从另一台机器迁移过来),可以跳过引导:
{
"agent": {
"skipBootstrap": true
}
}
也可以随时运行 openclaw setup 重建缺失的默认文件(不会覆盖已有文件)。
2. Agent 工作区
工作区(Workspace)是龙虾的"家"——它的身份、性格、记忆、技能全都存放在这里。
2.1 默认位置
~/.openclaw/workspace/
如果设置了 OPENCLAW_PROFILE(非 default),则默认位置变为 ~/.openclaw/workspace-<profile>。
2.2 工作区文件一览
| 文件 | 用途 | 加载时机 |
|---|---|---|
AGENTS.md | 操作指令:告诉龙虾"怎么做事"和如何使用记忆 | 每次会话开始 |
SOUL.md | 人设:性格、语气、边界 | 每次会话开始 |
USER.md | 用户资料:你是谁、怎么称呼你 | 每次会话开始 |
IDENTITY.md | 龙虾身份:名字、风格、表情符号 | 每次会话开始 |
TOOLS.md | 工具使用备注(不控制工具开关,只是使用建议) | 每次会话开始 |
HEARTBEAT.md | 心跳任务清单(可选,保持简短) | 心跳运行时 |
BOOT.md | 启动清单(可选,Gateway 重启时执行) | Gateway 启动时 |
BOOTSTRAP.md | 首次引导仪式(完成后删除) | 仅首次运行 |
MEMORY.md | 长期记忆(可选) | 仅主会话 |
memory/YYYY-MM-DD.md | 每日记忆日志 | 按需读取 |
skills/ | 工作区级技能(可选) | 按需加载 |
重要:这些文件在每次对话时都会注入到 AI 模型的上下文窗口中,会消耗 Token。保持文件简洁,尤其是
MEMORY.md——它会随时间增长,导致上下文使用量增大和更频繁的压缩。
memory/YYYY-MM-DD.md每日文件不会自动注入,而是通过memory_search和memory_get工具按需访问,不占用上下文窗口。
工作区文件注入规则
- 空文件会被跳过
- 大文件会被截断并标注
[truncated]- 单文件上限:
agents.defaults.bootstrapMaxChars(默认 20,000 字符) - 所有文件总上限:
agents.defaults.bootstrapTotalMaxChars(默认 150,000 字符)
- 单文件上限:
- 缺失的文件会注入一行 "missing file" 标记
- 子 Agent 会话只注入
AGENTS.md和TOOLS.md(其他文件被过滤以保持子 Agent 上下文精简) - 截断时可注入警告,通过
agents.defaults.bootstrapPromptTruncationWarning控制(off/once/always,默认once)
运行 /context list 或 /context detail 可以查看每个文件的原始大小 vs 注入大小、是否被截断。
工作区的安全边界
工作区是默认的工作目录(cwd),但不是硬沙盒。工具解析相对路径时会基于工作区,但绝对路径仍然可以访问主机上的其他位置。
如果你需要严格隔离,使用沙盒模式:
{
"agents": {
"defaults": {
"sandbox": {
"mode": "all",
"scope": "agent"
}
}
}
}
启用沙盒后,工具会在 ~/.openclaw/sandboxes 下的隔离目录中操作,而非主机工作区。
工作区 Git 备份(推荐)
建议将工作区放入私有 Git 仓库备份:
# 初始化
cd ~/.openclaw/workspace
git init
git add AGENTS.md SOUL.md TOOLS.md IDENTITY.md USER.md HEARTBEAT.md memory/
git commit -m "Add agent workspace"
# 添加远程仓库(GitHub CLI)
gh repo create openclaw-workspace --private --source . --remote origin --push
# 日常更新
git add .
git commit -m "Update memory"
git push
不要提交:API 密钥、OAuth 令牌、~/.openclaw/ 下的任何内容。
建议的 .gitignore:
.DS_Store
.env
**/*.key
**/*.pem
**/secrets*
2.3 哪些不在工作区
以下内容存储在 ~/.openclaw/ 下,不在工作区中:
| 路径 | 内容 |
|---|---|
~/.openclaw/openclaw.json | 全局配置 |
~/.openclaw/credentials/ | OAuth 令牌、API 密钥 |
~/.openclaw/agents/<id>/sessions/ | 会话记录 |
~/.openclaw/skills/ | 共享级技能 |
如果你需要迁移到新机器,配置和会话需要单独复制。
3. Agent 循环:从消息到回复
当你发送一条消息时,龙虾是如何处理并回复的?这个过程叫做 Agent 循环(Agent Loop)。
3.1 高层流程
你的消息
→ 路由(找到对应的 Agent 和会话)
→ 排队(如果正在处理另一条消息)
→ Agent 运行
→ 组装上下文(系统提示词 + 历史消息 + 工具列表)
→ 发送给 AI 模型
→ 模型思考并决定下一步
→ 执行工具调用(搜索、读写文件等)
→ 流式输出回复
→ 回复发送到聊天平台
3.2 运行串行化
为了保证会话一致性,同一个会话中的消息会排队依次处理,不会并行。这意味着如果龙虾正在处理你的上一条消息,新消息会进入队列等待。
不同会话(比如不同群聊)之间是并行的。通过
agents.defaults.maxConcurrent(默认 4)控制最大并行数。
Agent 运行的详细步骤
- 验证请求:检查参数、解析会话键
- 解析模型:确定使用哪个模型和认证信息
- 加载技能:加载技能快照并注入到环境和提示词中
- 准备工作区:解析工作区路径,沙盒运行可能重定向到沙盒工作区
- 构建系统提示词:组装 OpenClaw 的基础提示词、技能提示词、引导上下文
- 创建会话:获取写锁、打开 SessionManager 、准备流式输出
- 执行提示:调用
session.prompt()驱动完整的 Agent 循环 - 事件分发:将 pi-agent-core 的事件(工具调用、文本流、生命周期)桥接到 OpenClaw 的事件流
- 超时控制:
agents.defaults.timeoutSeconds(默认 600 秒)超时后中止运行
Agent 运行返回后,如果还有排队的消息,会继续处理下一条。
钩子系统(Hooks)
OpenClaw 提供两类钩子,允许你在关键节点插入自定义逻辑:
内部钩子(Gateway Hooks):
agent:bootstrap:引导文件构建前,可修改/替换引导上下文- 命令钩子:
/new、/reset、/stop等命令事件
插件钩子:
before_model_resolve:在模型解析前覆盖 provider/modelbefore_prompt_build:在提交前注入额外上下文或系统提示agent_end:运行完成后检查消息列表和元数据before_tool_call/after_tool_call:拦截工具参数/结果message_received/message_sending/message_sent:消息生命周期session_start/session_end:会话边界gateway_start/gateway_stop:网关生命周期
3.3 超时与中止
| 场景 | 默认值 | 说明 |
|---|---|---|
| Agent 运行超时 | 600 秒 | 超时后中止运行 |
agent.wait 等待超时 | 30 秒 | 仅等待超时,不会停止 Agent |
发送 /stop 可以中止当前运行、清除该会话的排队消息,并停止它派生的子 Agent。
4 系统提示词
每次 Agent 运行时,OpenClaw 都会构建一个自定义系统提示词——这是龙虾"看到"的第一段指令。
系统提示词包含以下部分:
| 部分 | 内容 |
|---|---|
| 工具列表 | 当前可用工具 + 简短描述 |
| 安全守则 | 避免越权行为的提醒 |
| 技能列表 | 可用技能的名称、描述和文件路径(模型需要时会读取 SKILL.md) |
| 工作区 | 工作目录路径 |
| 文档 | 本地 OpenClaw 文档路径 |
| 日期时间 | 用户时区 |
| 运行时信息 | 主机、操作系统、模型、思考级别 |
| 引导文件 | AGENTS.md、SOUL.md 等文件内容(注入到"项目上下文"中) |
安全守则是建议性的,它引导模型行为但不强制执行策略。真正的硬限制来自工具策略、exec 审批、沙盒和渠道白名单。
提示词模式
OpenClaw 支持三种提示词模式(由运行时自动设置,非用户配置):
| 模式 | 适用场景 | 包含内容 |
|---|---|---|
full | 默认 | 所有部分 |
minimal | 子 Agent | 省略技能、记忆召回、自更新、用户身份、心跳等 |
none | 最小化 | 仅基础身份行 |
minimal 模式下,注入的额外提示标注为"Subagent Context"而非"Group Chat Context"。
时间处理
系统提示词中包含"当前日期与时间"部分(前提是已知用户时区)。为了保持提示词缓存稳定,只包含时区信息而非动态时钟。
当 Agent 需要当前时间时,使用 session_status 工具(返回包含时间戳的状态卡片)。
配置项:
agents.defaults.userTimezone:用户时区agents.defaults.timeFormat:时间格式(auto/12/24)
5. 会话管理
会话(Session)是龙虾与你(或一个群聊)之间的对话记录。
5.1 会话键(Session Key)
OpenClaw 用 会话键 来区分不同的对话:
| 来源 | 会话键格式 | 说明 |
|---|---|---|
| 私聊(默认) | agent:main:main | 所有私聊共享一个会话 |
| 群聊 | agent:main:<channel>:group:<id> | 每个群独立 |
| Cron 任务 | cron:<job.id> | 每次运行独立会话 |
| 子 Agent | agent:main:subagent:<uuid> | 隔离的子任务 |
5.2 私聊隔离(dmScope)
默认情况下,所有私聊共享同一个会话(dmScope: "main")。这对单人使用很方便——你在飞书和 QQ 发消息,龙虾能记住上下文。
但如果多个人可以私聊你的龙虾,这就有隐私风险了:
安全警告:假设 Alice 和 Bob 都能私聊你的龙虾。Alice 聊了一个隐私话题,Bob 接着问"我们刚才在聊什么?"——由于共享会话,模型可能会用 Alice 的内容回答 Bob。
修复方法:设置 dmScope 隔离每个人的会话:
{
"session": {
"dmScope": "per-channel-peer"
}
}
| 模式 | 说明 | 适用场景 |
|---|---|---|
main | 所有私聊共享主会话 | 只有你一个人使用 |
per-peer | 按发送者隔离 | 多人使用,跨渠道合并同一人 |
per-channel-peer | 按渠道 + 发送者隔离 | 推荐——多人使用 |
per-account-channel-peer | 按账号 + 渠道 + 发送者隔离 | 多账号多人场景 |
运行
openclaw security audit可以检查你的 DM 安全设置。
身份关联(identityLinks)
如果同一个人在多个平台联系你的龙虾(比如 Telegram 和 Discord),你可以用 identityLinks 把他们的身份关联起来,让他们共享同一个私聊会话:
{
"session": {
"dmScope": "per-channel-peer",
"identityLinks": {
"alice": ["telegram:123456789", "discord:987654321012345678"]
}
}
}
这样 Alice 无论从 Telegram 还是 Discord 发消息,都在同一个会话中。
5.3 会话生命周期
会话不会永远持续——它们会按策略重置。
默认行为:每天凌晨 4:00(Gateway 所在机器的本地时间)自动重置。下次发消息时开始新会话。
{
"session": {
"reset": {
"mode": "daily",
"atHour": 4,
"idleMinutes": 120
}
}
}
| 重置触发 | 说明 |
|---|---|
| 每日重置 | 默认凌晨 4:00,上次更新早于该时间的会话视为过期 |
| 空闲重置 | 可选,空闲超过 N 分钟后重置(与每日重置取先到期者) |
| 手动重置 | 发送 /new 或 /reset 开始新会话 |
/new <model>还可以在重置的同时切换模型,例如/new Opus。
按类型 / 按渠道自定义重置策略
可以为不同类型的会话(私聊、群聊、线程)和不同渠道设置不同的重置策略:
{
"session": {
"resetByType": {
"direct": { "mode": "idle", "idleMinutes": 240 },
"group": { "mode": "idle", "idleMinutes": 120 },
"thread": { "mode": "daily", "atHour": 4 }
},
"resetByChannel": {
"discord": { "mode": "idle", "idleMinutes": 10080 }
}
}
}
resetByChannel 优先级高于 reset / resetByType。
5.4 会话存储与维护
会话记录存储为 JSONL 文件:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl
OpenClaw 会自动维护会话存储,防止无限增长:
| 配置项 | 默认值 | 说明 |
|---|---|---|
session.maintenance.mode | warn | warn 仅报告,enforce 自动清理 |
session.maintenance.pruneAfter | 30d | 清理超过 30 天的旧会话 |
session.maintenance.maxEntries | 500 | 最多保留 500 个会话条目 |
session.maintenance.rotateBytes | 10mb | sessions.json 超过此大小时轮转 |
生产环境建议:将
mode设为enforce,同时设置时间和数量限制。运行openclaw sessions cleanup --dry-run可以预览清理效果。
高级会话维护配置
启用磁盘预算(限制会话目录总大小):
{
"session": {
"maintenance": {
"mode": "enforce",
"maxDiskBytes": "1gb",
"highWaterBytes": "800mb"
}
}
}
大规模部署示例:
{
"session": {
"maintenance": {
"mode": "enforce",
"pruneAfter": "14d",
"maxEntries": 2000,
"rotateBytes": "25mb",
"maxDiskBytes": "2gb",
"highWaterBytes": "1.6gb"
}
}
}
CLI 命令:
# 预览清理效果
openclaw sessions cleanup --dry-run
# 执行清理
openclaw sessions cleanup --enforce
会话检查命令
| 命令 | 说明 |
|---|---|
openclaw status | 查看会话存储路径和最近会话 |
openclaw sessions --json | 导出所有会话条目 |
/status(在聊天中发送) | 查看上下文使用率、当前设置 |
/context list(在聊天中发送) | 查看系统提示词和注入文件 |
/stop(在聊天中发送) | 中止当前运行并清除排队消息 |
/compact(在聊天中发送) | 压缩旧上下文以释放窗口空间 |
5.5 会话工具
Agent 可以通过内置工具管理和跨会话通信:
| 工具 | 功能 |
|---|---|
sessions_list | 列出所有会话 |
sessions_history | 获取某个会话的对话记录 |
sessions_send | 向另一个会话发送消息(支持等待回复) |
sessions_spawn | 派生子 Agent 执行隔离任务 |
sessions_send 的工作方式
sessions_send 可以让一个 Agent 向另一个会话发送消息并等待回复:
timeoutSeconds = 0:发完即走(异步),返回{ runId, status: "accepted" }timeoutSeconds > 0:等待最多 N 秒,返回{ runId, status: "ok", reply }- 超时则返回
{ runId, status: "timeout" }
发送后会触发一个乒乓循环:请求方和目标方交替回复,最多 session.agentToAgent.maxPingPongTurns 轮(默认 5)。回复 REPLY_SKIP 可终止循环。
循环结束后,目标 Agent 会运行一个"宣告"步骤,将结果发送到目标渠道。回复 ANNOUNCE_SKIP 可以静默处理。
sessions_spawn 的工作方式
sessions_spawn 派生一个子 Agent 在隔离会话中执行任务:
参数:
- task(必填):任务描述
- label(可选):标签
- model(可选):覆盖模型
- thinking(可选):覆盖思考级别
- runTimeoutSeconds(可选):子 Agent 超时时间
- thread(可选):绑定到线程
- cleanup(可选):完成后是否删除(delete/keep,默认 keep)
- sandbox(可选):inherit/require
- attachments(可选):附件数组
子 Agent 的限制:
- 默认拥有完整工具集,但不包含会话工具
- 不能调用
sessions_spawn(不允许嵌套派生) - 通过
agents.list[].subagents.allowAgents控制可跨 Agent 派生 - 完成后自动归档(默认 60 分钟后)
6. 记忆系统
OpenClaw 的记忆是纯 Markdown 文件——文件就是真相来源,模型只"记住"被写到磁盘上的内容。
6.1 两层记忆
| 文件 | 用途 | 更新频率 |
|---|---|---|
memory/YYYY-MM-DD.md | 每日日志(追加写入) | 每天 |
MEMORY.md | 精选长期记忆 | 不定期 |
6.2 何时写记忆
- 决策、偏好、持久事实 → 写入
MEMORY.md - 日常笔记、运行上下文 → 写入
memory/YYYY-MM-DD.md - 如果有人说"记住这个",龙虾应该立即写到文件中(不要只放在"脑子里")
记忆系统仍在演进中。明确提醒龙虾**"把这个记下来"**会有帮助。
6.3 记忆搜索工具
| 工具 | 功能 |
|---|---|
memory_search | 语义搜索——即使措辞不同也能找到相关记忆 |
memory_get | 读取指定记忆文件的内容 |
6.4 自动记忆刷新
当会话接近自动压缩时,OpenClaw 会触发一次静默记忆刷新——提醒模型将重要信息写入磁盘,避免压缩后丢失。
{
"agents": {
"defaults": {
"compaction": {
"memoryFlush": {
"enabled": true,
"softThresholdTokens": 4000
}
}
}
}
}
这个过程对用户不可见(使用
NO_REPLY静默处理)。
向量记忆搜索(语义检索)
OpenClaw 可以为 MEMORY.md 和 memory/*.md 构建向量索引,通过语义相似度搜索(即使措辞不同也能匹配)。
默认启用,自动监控记忆文件变化。
嵌入提供商选择(自动检测顺序):
- 本地模型(如果配置了
memorySearch.local.modelPath) - OpenAI(如果有 API Key)
- Gemini(如果有 API Key)
- Voyage / Mistral(如果有 API Key)
- Ollama(需手动指定
provider: "ollama")
配置示例(使用 Gemini 嵌入):
{
"agents": {
"defaults": {
"memorySearch": {
"provider": "gemini",
"model": "gemini-embedding-001",
"remote": {
"apiKey": "你的 Gemini API Key"
}
}
}
}
}
混合搜索(BM25 + 向量): 结合语义匹配("这段话意思相近")和关键词匹配(精确的 ID、代码符号、错误信息),提供更全面的搜索结果。
{
"agents": {
"defaults": {
"memorySearch": {
"query": {
"hybrid": {
"enabled": true,
"vectorWeight": 0.7,
"textWeight": 0.3
}
}
}
}
}
}
高级记忆搜索配置
MMR 去重(减少重复结果):
当搜索结果中有多个近似重复的笔记时(常见于每日日志重复记录同一主题),启用 MMR 可以提高结果多样性:
{
"agents": {
"defaults": {
"memorySearch": {
"query": {
"hybrid": {
"mmr": {
"enabled": true,
"lambda": 0.7
}
}
}
}
}
}
}
lambda:0 = 最大多样性,1 = 最大相关性,默认 0.7(平衡偏相关)。
时间衰减(优先近期记忆):
对于积累了大量每日笔记的 Agent,旧笔记可能因措辞更好而排名超过昨天的更新。启用时间衰减可以让近期记忆自然排名更高:
{
"agents": {
"defaults": {
"memorySearch": {
"query": {
"hybrid": {
"temporalDecay": {
"enabled": true,
"halfLifeDays": 30
}
}
}
}
}
}
}
半衰期 30 天的效果:今天 100%、7 天前 84%、30 天前 50%、90 天前 11.5%。
永久文件不受衰减影响:MEMORY.md 和 memory/ 下非日期命名的文件(如 memory/projects.md)永远保持原始分数。
额外记忆路径:
{
"agents": {
"defaults": {
"memorySearch": {
"extraPaths": ["../team-docs", "/srv/shared-notes/overview.md"]
}
}
}
}
QMD 后端(实验性高级搜索)
QMD 是一个本地优先的搜索引擎,结合 BM25 + 向量 + 重排序,提供更强大的记忆搜索。
启用方式:
{
"memory": {
"backend": "qmd"
}
}
前提条件:
- 安装 QMD CLI:
bun install -g https://github.com/tobi/qmd - macOS 需要
brew install sqlite(支持扩展的 SQLite) - QMD 自动从 HuggingFace 下载 GGUF 模型,首次搜索可能较慢
- Windows 建议通过 WSL2 使用
QMD 完全本地运行,Markdown 文件仍然是数据来源。如果 QMD 失败,OpenClaw 自动回退到内置 SQLite 搜索。
7.上下文
上下文(Context)是 OpenClaw 发送给模型的全部内容,受限于模型的上下文窗口(Token 上限)。
上下文包含:
- 系统提示词(所有部分)
- 对话历史(你的消息 + 龙虾的回复)
- 工具调用与结果
- 附件(图片、音频、文件)
- 压缩摘要(如果发生过压缩)
上下文 ≠ 记忆。记忆存储在磁盘上,可以跨会话加载;上下文是模型当前窗口中的内容。
7.1 查看上下文使用情况
在对话中发送以下命令:
| 命令 | 作用 |
|---|---|
/status | 快速查看上下文使用率 + 会话设置 |
/context list | 查看注入的文件和大致大小 |
/context detail | 详细分解:每个文件、工具 Schema、技能条目的大小 |
/usage tokens | 在每次回复后追加 Token 使用量 |
7.2 上下文消耗的两大隐形成本
技能列表:系统提示词中的技能列表(名称 + 描述 + 路径)有实际开销。技能的详细指令不会默认包含——模型在需要时才会读取 SKILL.md。
工具 Schema:工具影响上下文的两个方面:
- 系统提示词中的工具列表文本(你能看到的部分)
- 工具 Schema(JSON 格式,发送给模型以便调用工具,看不见但占用空间)
/context detail 会列出最大的工具 Schema,让你知道哪些工具占用最多空间。例如 browser 工具的 Schema 通常约 2,500 Token。