Docs: update zh-CN translations and pipeline

What:
- update zh-CN glossary, TM, and translator prompt
- regenerate zh-CN docs and apply targeted fixes
- add zh-CN AGENTS pipeline guidance

Why:
- address terminology/spacing feedback from #6995

Tests:
- pnpm build && pnpm check && pnpm test
This commit is contained in:
Josh Palmer
2026-02-03 13:23:00 -08:00
parent 9f03791aa9
commit a3ec2d0734
228 changed files with 10651 additions and 10475 deletions
+48 -52
View File
@@ -4,147 +4,143 @@ read_when:
summary: 智能体循环生命周期、流和等待语义
title: 智能体循环
x-i18n:
generated_at: "2026-02-01T20:22:03Z"
generated_at: "2026-02-03T10:05:11Z"
model: claude-opus-4-5
provider: pi
source_hash: 0775b96eb3451e137297661a1095eaefb2bafeebb5f78123174a46290e18b014
source_path: concepts/agent-loop.md
workflow: 14
workflow: 15
---
# 智能体循环(OpenClaw
智能体循环是智能体的一次完整"真实"运行:接收 → 上下文组装 → 模型推理 →
工具执行 → 流式回复 → 持久化。它是将消息转化为操作和最终回复的权威路径,同时保持会话状态的一致性。
智能体循环是智能体的完整"真实"运行:接收 → 上下文组装 → 模型推理 → 工具执行 → 流式回复 → 持久化。这是将消息转化为操作和最终回复的权威路径,同时保持会话状态的一致性。
在 OpenClaw 中,循环是每个会话的单次序列化运行,在模型思考、调用工具和流式输出时发出生命周期和流事件。本文档解释了这个完整循环是如何端到端连接的。
在 OpenClaw 中,循环是每个会话的单次序列化运行,在模型思考、调用工具和流式输出时发出生命周期和流事件。本文档解释了这个真实循环是如何端到端连接的。
## 入口点
- Gateway网关 RPC`agent``agent.wait`
- Gateway 网关 RPC`agent``agent.wait`
- CLI`agent` 命令。
## 工作原理(高层概述
## 工作原理(高层
1. `agent` RPC 验证参数,解析会话(sessionKey/sessionId),持久化会话元数据,立即返回 `{ runId, acceptedAt }`
2. `agentCommand` 运行智能体:
- 解析模型 + thinking/verbose 默认值
- 解析模型 + 思考/详细模式默认值
- 加载 Skills 快照
- 调用 `runEmbeddedPiAgent`pi-agent-core 运行时)
- 如果嵌入式循环未发出**生命周期 end/error** 事件,则补充发出
- 如果嵌入式循环未发出**生命周期结束/错误**事件,则发出该事件
3. `runEmbeddedPiAgent`
- 通过每会话 + 全局队列序列化运行
- 解析模型 + 认证配置并构建 pi 会话
- 解析模型 + 认证配置文件并构建 pi 会话
- 订阅 pi 事件并流式传输助手/工具增量
- 强制执行超时 -> 超时则中止运行
- 返回载 + 使用元数据
- 返回有效负载 + 使用元数据
4. `subscribeEmbeddedPiSession` 将 pi-agent-core 事件桥接到 OpenClaw `agent` 流:
- 工具事件 => `stream: "tool"`
- 助手增量 => `stream: "assistant"`
- 生命周期事件 => `stream: "lifecycle"``phase: "start" | "end" | "error"`
5. `agent.wait` 使用 `waitForAgentJob`
- 等待 `runId` 的**生命周期 end/error**
- 等待 `runId` 的**生命周期结束/错误**
- 返回 `{ status: ok|error|timeout, startedAt, endedAt, error? }`
## 队列 + 并发
- 运行按会话键(会话通道)序列化,可选择通过全局通道进行
- 运行按会话键(会话通道)序列化,可选择通过全局通道。
- 这可以防止工具/会话竞争并保持会话历史的一致性。
- 消息渠道可以选择队列模式(collect/steer/followup)来供给此通道系统。
参见[命令队列](/concepts/queue)。
- 消息渠道可以选择队列模式(collect/steer/followup)来馈送此通道系统。参见[命令队列](/concepts/queue)。
## 会话 + 工作区准备
- 工作区被解析并创建;沙箱运行可能会重定向到沙箱工作区根目录。
- Skills 被加载(或从快照中复用)并注入到环境和提示中。
- 引导/上下文文件被解析并注入到系统提示报告中。
- 解析并创建工作区;沙箱隔离运行可能会重定向到沙箱工作区根目录。
- 加载 Skills(或从快照中复用)并注入到环境和提示中。
- 解析引导/上下文文件并注入到系统提示报告中。
- 获取会话写锁;在流式传输之前打开并准备 `SessionManager`
## 提示组装 + 系统提示
- 系统提示由 OpenClaw 的基础提示、Skills 提示、引导上下文和每次运行的覆盖构建而成
- 强制执行模型特定的限制和压缩留令牌
- 参见[系统提示](/concepts/system-prompt)了解模型看到的内容。
- 系统提示由 OpenClaw 的基础提示、Skills 提示、引导上下文和每次运行的覆盖构建。
- 强制执行模型特定的限制和压缩留令牌。
- 参见[系统提示](/concepts/system-prompt)了解模型看到的内容。
## 钩子点(可拦截的位置)
## 钩子点(可拦截的位置)
OpenClaw 有两个钩子系统:
- **内部钩子**(Gateway网关钩子):用于命令和生命周期事件的事件驱动脚本。
- **插件钩子**:智能体/工具生命周期和 Gateway网关管道中的扩展点。
- **内部钩子**Gateway 网关钩子):用于命令和生命周期事件的事件驱动脚本。
- **插件钩子**:智能体/工具生命周期和 Gateway 网关管道中的扩展点。
### 内部钩子(Gateway网关钩子)
### 内部钩子(Gateway 网关钩子)
- **`agent:bootstrap`**:在系统提示最终确定之前构建引导文件时运行。
用于添加/移除引导上下文文件。
- **`agent:bootstrap`**:在系统提示最终确定之前构建引导文件时运行。用于添加/删除引导上下文文件。
- **命令钩子**`/new``/reset``/stop` 和其他命令事件(参见钩子文档)。
参见[钩子](/hooks)了解设置和示例。
### 插件钩子(智能体 + Gateway网关生命周期)
### 插件钩子(智能体 + Gateway 网关生命周期)
这些在智能体循环或 Gateway网关管道内运行:
这些在智能体循环或 Gateway 网关管道内运行:
- **`before_agent_start`**:在运行开始前注入上下文或覆盖系统提示。
- **`agent_end`**:在完成后检查最终消息列表和运行元数据。
- **`before_compaction` / `after_compaction`**:观察或注压缩周期。
- **`before_compaction` / `after_compaction`**:观察或注压缩周期。
- **`before_tool_call` / `after_tool_call`**:拦截工具参数/结果。
- **`tool_result_persist`**:在工具结果写入会话记录之前同步转换工具结果
- **`tool_result_persist`**:在工具结果写入会话记录之前同步转换它们
- **`message_received` / `message_sending` / `message_sent`**:入站 + 出站消息钩子。
- **`session_start` / `session_end`**:会话生命周期边界。
- **`gateway_start` / `gateway_stop`**:Gateway网关生命周期事件。
- **`gateway_start` / `gateway_stop`**Gateway 网关生命周期事件。
参见[插件](/plugin#plugin-hooks)了解钩子 API 和注册详情。
## 流式传输 + 部分回复
- 助手增量从 pi-agent-core 流式传输并作为 `assistant` 事件发出。
- 块流式传输可以在 `text_end``message_end` 时发出部分回复。
- 块流式传输可以在 `text_end``message_end` 时发出部分回复。
- 推理流式传输可以作为单独的流或作为块回复发出。
- 参见[流式传输](/concepts/streaming)了解分块和块回复行为。
## 工具执行 + 消息工具
- 工具的 start/update/end 事件在 `tool` 流上发出。
- 工具结果在记录/发出之前会对大小和图片载荷进行清理。
- 消息工具发送会被跟踪以抑制重复的助手确认。
- 工具开始/更新/结束事件在 `tool` 流上发出。
- 工具结果在记录/发出之前会对大小和图像有效负载进行清理。
- 消息工具发送会被跟踪以抑制重复的助手确认。
## 回复整形 + 抑制
- 最终载由以下内容组装:
- 助手文本(可选的推理内容
- 内联工具摘要(当 verbose + 允许时)
- 最终有效负载由以下内容组装:
- 助手文本(可选的推理)
- 内联工具摘要(当详细模式 + 允许时)
- 模型出错时的助手错误文本
- `NO_REPLY` 被视为静默令牌,从传出载荷中过滤。
- 消息工具重复项从最终载列表中移除。
- 如果没有可渲染的载且工具出错,则发出回退工具错误回复
(除非消息工具已发送了用户可见的回复)。
- `NO_REPLY` 被视为静默令牌,从出站有效负载中过滤。
- 消息工具重复项从最终有效负载列表中移除。
- 如果没有剩余可渲染的有效负载且工具出错,则发出回退工具错误回复(除非消息工具已经发送了用户可见的回复)。
## 压缩 + 重试
- 自动压缩发出 `compaction` 流事件,并可能触发重试。
- 重试时,内存缓冲区和工具摘要会重置以避免重复输出。
- 自动压缩发出 `compaction` 流事件,可以触发重试。
- 重试时,内存缓冲区和工具摘要会重置以避免重复输出。
- 参见[压缩](/concepts/compaction)了解压缩管道。
## 事件流(当前)
- `lifecycle`:由 `subscribeEmbeddedPiSession` 发出(以及作为 `agentCommand` 的回退)
- `assistant`来自 pi-agent-core 流式增量
- `tool`来自 pi-agent-core 流式工具事件
- `assistant` pi-agent-core 流式传输的增量
- `tool` pi-agent-core 流式传输的工具事件
## 聊天渠道处理
- 助手增量被缓冲聊天 `delta` 消息。
- 在**生命周期 end/error** 时发出聊天 `final`
- 助手增量被缓冲聊天 `delta` 消息
- 在**生命周期结束/错误**时发出聊天 `final`
## 超时
- `agent.wait` 默认30 秒(仅等待阶段)。`timeoutMs` 参数可覆盖。
- `agent.wait` 默认:30 秒(仅等待)。`timeoutMs` 参数可覆盖。
- 智能体运行时:`agents.defaults.timeoutSeconds` 默认 600 秒;在 `runEmbeddedPiAgent` 中止计时器中强制执行。
## 可能提前结束的情况
- 智能体超时(中止)
- AbortSignal(取消)
- Gateway网关断开连接或 RPC 超时
- `agent.wait` 超时(仅等待阶段,不会停止智能体)
- Gateway 网关断开连接或 RPC 超时
- `agent.wait` 超时(仅等待,不会停止智能体)
+59 -54
View File
@@ -1,30 +1,32 @@
---
read_when:
- 你需要解释智能体工作区或其文件布局
- 你想备份或迁移智能体工作区
- 你想备份或迁移智能体工作区
summary: 智能体工作区:位置、布局和备份策略
title: 智能体工作区
x-i18n:
generated_at: "2026-02-01T20:22:05Z"
generated_at: "2026-02-03T07:45:49Z"
model: claude-opus-4-5
provider: pi
source_hash: 84c550fd89b5f2474aeae586795485fd29d36effbb462f13342b31540fc18b82
source_path: concepts/agent-workspace.md
workflow: 14
workflow: 15
---
# 智能体工作区
工作区是智能体的主目录。它是文件工具和工作区上下文使用的唯一工作目录。请将其保持私密,并视为记忆来对待
工作区是智能体的。它是文件工具和工作区上下文使用的唯一工作目录。请保持私密性并将其视为记忆。
`~/.openclaw/` 是分开的,后者存储配置、凭和会话。
`~/.openclaw/` 是分开的,后者存储配置、凭和会话。
**重要提示** 工作区是**默认工作目录**,而硬性沙箱。工具会基于工作区解析相对路径,但绝对路径仍然可以访问主机上的其他位置,除非启用了沙箱。如果你需要隔离,请使用 [`agents.defaults.sandbox`](/gateway/sandboxing)(和/或按智能体的沙箱配置)。当启用沙箱且 `workspaceAccess` 不是 `"rw"` 时,工具在 `~/.openclaw/sandboxes` 下的沙箱工作区中运行,而非你的主机工作区。
**重要:** 工作区是**默认 cwd**,而不是硬性沙箱。工具会根据工作区解析相对路径,但绝对路径仍然可以访问主机上的其他位置,除非启用了沙箱隔离。如果你需要隔离,请使用
[`agents.defaults.sandbox`](/gateway/sandboxing)(和/或每智能体沙箱配置)。
当启用沙箱隔离且 `workspaceAccess` 不是 `"rw"` 时,工具在 `~/.openclaw/sandboxes` 下的沙箱工作区内操作,而不是你的主机工作区。
## 默认位置
- 默认:`~/.openclaw/workspace`
- 如果设置了 `OPENCLAW_PROFILE` 且不是 `"default"`默认变为
- 如果设置了 `OPENCLAW_PROFILE` 且不是 `"default"`,默认变为
`~/.openclaw/workspace-<profile>`
-`~/.openclaw/openclaw.json` 中覆盖:
@@ -36,9 +38,9 @@ x-i18n:
}
```
`openclaw onboard``openclaw configure``openclaw setup` 将创建工作区并在引导文件缺失时生成它们
`openclaw onboard``openclaw configure``openclaw setup` 将创建工作区并在缺失时填充引导文件。
如果你已经自管理工作区文件,可以禁用引导文件创建:
如果你已经自管理工作区文件,可以禁用引导文件创建:
```json5
{ agent: { skipBootstrap: true } }
@@ -46,20 +48,21 @@ x-i18n:
## 额外的工作区文件夹
较旧的安装可能创建了 `~/openclaw`。保留多个工作区目录可能会导致认证或状态不一致的困惑,因为同一时间只有一个工作区处于活跃状态
旧版安装可能创建了 `~/openclaw`。保留多个工作区目录可能会导致混乱的认证或状态漂移,因为同一时间只有一个工作区是活动的
**建议:** 保持单一活跃工作区。如果你不再使用额外的文件夹,请将其归档或移至回收站(例如 `trash ~/openclaw`)。如果你有意保留多个工作区,请确保 `agents.defaults.workspace` 指向活跃的那个。
**建议:** 保持单个活动工作区。如果你不再使用额外的文件夹,请归档或移至废纸篓(例如 `trash ~/openclaw`)。
如果你有意保留多个工作区,请确保 `agents.defaults.workspace` 指向活动的那个。
`openclaw doctor` 在检测到额外工作区目录时会发出警告。
## 工作区文件映射(每个文件的含义)
以下是 OpenClaw 在工作区期望的标准文件:
这些是 OpenClaw 在工作区期望的标准文件:
- `AGENTS.md`
- 智能体的操作指以及它应如何使用记忆。
- 智能体的操作指以及它应如何使用记忆。
- 在每个会话开始时加载。
- 适合放置规则、优先级和"行为方式"的详细说明
- 适合放置规则、优先级和"如何行为"的详细信息
- `SOUL.md`
- 人设、语气和边界。
@@ -74,61 +77,62 @@ x-i18n:
- 在引导仪式期间创建/更新。
- `TOOLS.md`
- 关于本地工具和约定的说明
- 关于本地工具和惯例的注释
- 不控制工具可用性;仅作为指导。
- `HEARTBEAT.md`
- 可选的心跳运行小清单。
- 保持简短以避免消耗令牌
- 可选的心跳运行小型检查清单。
- 保持简短以避免 token 消耗。
- `BOOT.md`
- 可选的启动清单,在启用内部钩子时于 Gateway网关重启时执行。
- 保持简短;使用消息工具进行外发
- 当启用内部 hooks 时,在 Gateway 网关重启时执行的可选启动检查清单
- 保持简短;使用 message 工具进行出站发送
- `BOOTSTRAP.md`
- 一次性首次运行仪式。
- 仅为全新工作区创建。
- 仪式完成后删除它。
- 仪式完成后删除它。
- `memory/YYYY-MM-DD.md`
- 每日记忆日志(每天一个文件)。
- 建议在会话开始时读取今天昨天的内容。
- 建议在会话开始时读取今天 + 昨天的内容。
- `MEMORY.md`(可选)
- 精选的长期记忆。
- 仅在主要的私人会话中加载(不在共享/群组上下文中)。
- 仅在主私密会话中加载(不在共享/群组上下文中)。
参见[记忆](/concepts/memory)了解工作流程和自动记忆刷
参见 [记忆](/concepts/memory) 了解工作流程和自动记忆刷
- `skills/`(可选)
- 工作区特定的 Skills。
- 名称冲突时覆盖托管/内置 Skills。
- 名称冲突时覆盖托管/捆绑的 Skills。
- `canvas/`(可选)
- 用于节点显示的 Canvas UI 文件(例如 `canvas/index.html`)。
如果任何引导文件缺失,OpenClaw 会在会话中注入"文件缺失"标记并继续运行。大型引导文件在注入时会被截断;可通过 `agents.defaults.bootstrapMaxChars`(默认:20000调整限制。`openclaw setup` 可以重新创建缺失的默认文件而不会覆盖现有文件
如果任何引导文件缺失,OpenClaw 会在会话中注入"缺失文件"标记并继续。大型引导文件在注入时会被截断;使用 `agents.defaults.bootstrapMaxChars` 调整限制(默认:20000)。
`openclaw setup` 可以重新创建缺失的默认值而不覆盖现有文件。
## 不在工作区中的内容
## 工作区中不包含的内容
以下内容位于 `~/.openclaw/` 下,**不应**提交到工作区仓库:
这些位于 `~/.openclaw/` 下,不应提交到工作区仓库:
- `~/.openclaw/openclaw.json`(配置)
- `~/.openclaw/credentials/`OAuth 令牌、API 密钥)
- `~/.openclaw/agents/<agentId>/sessions/`(会话记录元数据)
- `~/.openclaw/skills/`(托管 Skills
- `~/.openclaw/credentials/`OAuth token、API 密钥)
- `~/.openclaw/agents/<agentId>/sessions/`(会话记录 + 元数据)
- `~/.openclaw/skills/`(托管 Skills
如果你需要迁移会话或配置,请单独复制它们并将排除在版本控制之外。
如果你需要迁移会话或配置,请单独复制它们并将它们排除在版本控制之外。
## Git 备份(推荐,私有)
将工作区视为私记忆。将其放入一个**私有** git 仓库中,以便备份和恢复。
将工作区视为私记忆。将其放入**私有** git 仓库以便备份和恢复。
在 Gateway网关运行的机器上执行以下步骤(工作区就在那里)。
运行 Gateway 网关的机器上执行这些步骤(工作区就在那里)。
### 1) 初始化仓库
### 1初始化仓库
如果安装了 git,全新工作区会自动初始化。如果此工作区尚未是仓库,请运行:
如果安装了 git,全新工作区会自动初始化。如果此工作区还不是仓库,请运行:
```bash
cd ~/.openclaw/workspace
@@ -137,14 +141,14 @@ git add AGENTS.md SOUL.md TOOLS.md IDENTITY.md USER.md HEARTBEAT.md memory/
git commit -m "Add agent workspace"
```
### 2) 添加私有远程仓库(新手友好选项)
### 2添加私有远程(适合初学者的选项)
选项 AGitHub 网页界面
1. 在 GitHub 上创建一个新的**私有**仓库。
2. 不要使用 README 初始化(避免合并冲突)。
1. 在 GitHub 上创建新的**私有**仓库。
2. 不要用 README 初始化(避免合并冲突)。
3. 复制 HTTPS 远程 URL。
4. 添加远程仓库并推送:
4. 添加远程并推送:
```bash
git branch -M main
@@ -152,7 +156,7 @@ git remote add origin <https-url>
git push -u origin main
```
选项 BGitHub CLI (`gh`)
选项 BGitHub CLI`gh`
```bash
gh auth login
@@ -161,10 +165,10 @@ gh repo create openclaw-workspace --private --source . --remote origin --push
选项 CGitLab 网页界面
1. 在 GitLab 上创建一个新的**私有**仓库。
2. 不要使用 README 初始化(避免合并冲突)。
1. 在 GitLab 上创建新的**私有**仓库。
2. 不要用 README 初始化(避免合并冲突)。
3. 复制 HTTPS 远程 URL。
4. 添加远程仓库并推送:
4. 添加远程并推送:
```bash
git branch -M main
@@ -172,7 +176,7 @@ git remote add origin <https-url>
git push -u origin main
```
### 3) 持续更新
### 3持续更新
```bash
git status
@@ -185,13 +189,13 @@ git push
即使在私有仓库中,也要避免在工作区中存储密钥:
- API 密钥、OAuth 令牌、密码或私有凭
- API 密钥、OAuth token、密码或私有凭
- `~/.openclaw/` 下的任何内容。
- 聊天记录的原始转储或敏感附件。
- 聊天的原始转储或敏感附件。
如果你必须存储敏感引用,请使用占位符并将真密钥保存在其他地方(密码管理器、环境变量或 `~/.openclaw/`)。
如果你必须存储敏感引用,请使用占位符并将真正的密钥保存在其他地方(密码管理器、环境变量或 `~/.openclaw/`)。
建议的 `.gitignore` 起始内容
建议的 `.gitignore` 起始配置
```gitignore
.DS_Store
@@ -203,12 +207,13 @@ git push
## 将工作区迁移到新机器
1. 将仓库克隆到目标路径(默认 `~/.openclaw/workspace`)。
1. 将仓库克隆到所需路径(默认 `~/.openclaw/workspace`)。
2.`~/.openclaw/openclaw.json` 中将 `agents.defaults.workspace` 设置为该路径。
3. 运行 `openclaw setup --workspace <path>` 以生成任何缺失的文件。
4. 如果你需要会话记录,请从旧机器单独复制 `~/.openclaw/agents/<agentId>/sessions/`
3. 运行 `openclaw setup --workspace <path>` 来填充任何缺失的文件。
4. 如果你需要会话,请单独从旧机器复制 `~/.openclaw/agents/<agentId>/sessions/`
## 高级说明
## 高级注意事项
- 多智能体路由可以为每个智能体使用不同的工作区。参见[渠道路由](/concepts/channel-routing)了解路由配置。
- 如果启用了 `agents.defaults.sandbox`,非主要会话可以使用 `agents.defaults.sandbox.workspaceRoot` 下的按会话沙箱工作区
- 多智能体路由可以为每个智能体使用不同的工作区。参见
[渠道路由](/concepts/channel-routing) 了解路由配置
- 如果启用了 `agents.defaults.sandbox`,非主会话可以在 `agents.defaults.sandbox.workspaceRoot` 下使用每会话沙箱工作区。
+36 -35
View File
@@ -1,51 +1,51 @@
---
read_when:
- 更改智能体运行时、工作区引导或会话行为
- 更改智能体运行时、工作区引导或会话行为
summary: 智能体运行时(嵌入式 pi-mono)、工作区契约和会话引导
title: 智能体运行时
x-i18n:
generated_at: "2026-02-01T20:22:02Z"
generated_at: "2026-02-03T10:04:53Z"
model: claude-opus-4-5
provider: pi
source_hash: 04b4e0bc6345d2afd9a93186e5d7a02a393ec97da2244e531703cb6a1c182325
source_path: concepts/agent.md
workflow: 14
workflow: 15
---
# 智能体运行时 🤖
OpenClaw 运行一个源自 **pi-mono**单一嵌入式智能体运行时。
OpenClaw 运行一个源自 **pi-mono** 的嵌入式智能体运行时。
## 工作区(必需)
OpenClaw 使用单一智能体工作区目录(`agents.defaults.workspace`)作为智能体工具和上下文的**唯一**工作目录(`cwd`)。
OpenClaw 使用单一智能体工作区目录(`agents.defaults.workspace`)作为智能体**唯一**工作目录(`cwd`,用于工具和上下文
建议:使用 `openclaw setup` 创建 `~/.openclaw/openclaw.json`(如果不存在)并初始化工作区文件。
建议:使用 `openclaw setup` 在缺失时创建 `~/.openclaw/openclaw.json` 并初始化工作区文件。
完整工作区布局 + 备份指南:[智能体工作区](/concepts/agent-workspace)
完整工作区布局 + 备份指南:[智能体工作区](/concepts/agent-workspace)
如果启用了 `agents.defaults.sandbox`,非主会话可以使用 `agents.defaults.sandbox.workspaceRoot`按会话工作区覆盖此设置(参见 [Gateway网关配置](/gateway/configuration))。
如果启用了 `agents.defaults.sandbox`,非主会话可以 `agents.defaults.sandbox.workspaceRoot`使用按会话隔离的工作区覆盖此设置(参见 [Gateway 网关配置](/gateway/configuration))。
## 引导文件(注入)
`agents.defaults.workspace` 内,OpenClaw 期望这些用户可编辑的文件:
`agents.defaults.workspace` 内,OpenClaw 期望以下用户可编辑的文件:
- `AGENTS.md` — 操作指令 + "记忆"
- `SOUL.md`角色设定、边界、语气
- `SOUL.md`人设、边界、语气
- `TOOLS.md` — 用户维护的工具说明(例如 `imsg``sag`、约定)
- `BOOTSTRAP.md` — 一次性首次运行仪式(完成后删除)
- `IDENTITY.md` — 智能体名称/风格/表情符号
- `USER.md` — 用户档案 + 首选称呼
- `IDENTITY.md` — 智能体名称/风格/表情
- `USER.md` — 用户档案 + 偏好称呼
在新会话的第一轮对话中OpenClaw 将这些文件的内容直接注入智能体上下文
在新会话的第一轮,OpenClaw 将这些文件的内容直接注入智能体上下文。
文件会被跳过。大文件会被剪和截断并附带标记,以保持提示词精简(阅读完整文件获取全部内容)。
空文件会被跳过。大文件会被剪和截断并添加标记,以保持提示词精简(阅读文件获取完整内容)。
如果文件缺失,OpenClaw 会注入一行"文件缺失"标记(`openclaw setup` 创建安全的默认模板)。
如果文件缺失,OpenClaw 会注入一行"文件缺失"标记(`openclaw setup` 创建安全的默认模板)。
`BOOTSTRAP.md` 仅在**全新工作区**(没有其他引导文件存在)时创建。如果你在完成仪式后删除它,后续重启时不会重新创建。
`BOOTSTRAP.md` 仅在**全新工作区**(没有其他引导文件存在)时创建。如果你在完成仪式后删除它,后续重启不应重新创建。
要完全禁用引导文件创建(用于预填充的工作区),请设置:
要完全禁用引导文件创建(用于预工作区),请设置:
```json5
{ agent: { skipBootstrap: true } }
@@ -53,24 +53,24 @@ OpenClaw 使用单一智能体工作区目录(`agents.defaults.workspace`
## 内置工具
核心工具(read/exec/edit/write 及相关系统工具)始终可用,受工具策略约束。`apply_patch` 是可选的,由 `tools.exec.applyPatch` 控制。`TOOLS.md` **不**控制哪些工具存在;它是关于希望如何使用这些工具的指导。
核心工具(read/exec/edit/write 及相关系统工具)始终可用,受工具策略约束。`apply_patch` 是可选的,由 `tools.exec.applyPatch` 控制。`TOOLS.md` **不**控制哪些工具存在;它是关于*你*希望如何使用它们的指导。
## Skills
OpenClaw 从三个位置加载 Skills(名称冲突时工作区优先):
- 内置(随安装包附带
- 内置(随安装包提供
- 托管/本地:`~/.openclaw/skills`
- 工作区:`<workspace>/skills`
Skills 可通过配置/环境变量进行控制(参见 [Gateway网关配置](/gateway/configuration) 中的 `skills`)。
Skills 可通过配置/环境变量控制(参见 [Gateway 网关配置](/gateway/configuration) 中的 `skills`)。
## pi-mono 集成
OpenClaw 复用 pi-mono 代码库的部分内容(模型/工具),但**会话管理、发现和工具连接由 OpenClaw 负责**。
OpenClaw 复用 pi-mono 代码库的部分内容(模型/工具),但**会话管理、设备发现和工具连接由 OpenClaw 负责**。
- 没有 pi-coding 智能体运行时。
-读取 `~/.pi/agent``<workspace>/.pi` 设置。
- pi-coding 智能体运行时。
- 不读取 `~/.pi/agent``<workspace>/.pi` 设置。
## 会话
@@ -79,30 +79,31 @@ OpenClaw 复用了 pi-mono 代码库的部分内容(模型/工具),但**
- `~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl`
会话 ID 是稳定的,由 OpenClaw 选择。
**不**读取旧版 Pi/Tau 会话文件夹。
**不**读取旧版 Pi/Tau 会话文件夹。
## 流式传输期间的引导
## 流式传输的引导
当队列模式为 `steer` 时,入站消息会注入当前运行中。队列在**每次工具调用后**检查;如果存在排队消息,当前助手消息的剩余工具调用会被跳过(工具结果显示"Skipped due to queued user message."错误),然后在下一个助手响应之前注入排队的用户消息
当队列模式为 `steer` 时,入站消息会注入当前运行。
队列在**每次工具调用后**检查;如果存在排队消息,当前助手消息的剩余工具调用将被跳过(工具结果显示错误"Skipped due to queued user message."),然后在下一个助手响应前注入排队的用户消息。
当队列模式为 `followup``collect` 时,入站消息会保留到当前轮次结束,然后使用排队的载开始新的智能体轮次。参见[队列](/concepts/queue)了解模式 + 防抖/上限行为。
当队列模式为 `followup``collect` 时,入站消息会保留到当前轮次结束,然后使用排队的载开始新的智能体轮次。参见 [队列](/concepts/queue) 了解模式 + 防抖/上限行为。
块流式传输在完成的助手块完成后立即发送;**默认关闭**`agents.defaults.blockStreamingDefault: "off"`)。
块流式传输在助手块完成后立即发送;默认为**关闭**`agents.defaults.blockStreamingDefault: "off"`)。
通过 `agents.defaults.blockStreamingBreak` 调整边界(`text_end``message_end`;默认为 text_end)。
使用 `agents.defaults.blockStreamingChunk` 控制软块分块(默认 800–1200 字符;优先段落分隔,其次换行;最后是句子)。
使用 `agents.defaults.blockStreamingCoalesce` 合并流式块以减少单行刷屏(基于空闲的合并后再发送)。非 Telegram 渠道需要显式设置 `*.blockStreaming: true` 以启用块回复。
详细的工具摘要在工具启动时发出(无防抖);Control UI 在可用时通过智能体事件流式传输工具输出。
使用 `agents.defaults.blockStreamingCoalesce` 合并流式块以减少单行刷屏(发送前基于空闲的合并)。非 Telegram 渠道需要显式设置 `*.blockStreaming: true` 以启用块回复。
工具启动时发出详细工具摘要(无防抖);Control UI 在可用时通过智能体事件流式传输工具输出。
更多详情:[流式传输 + 分块](/concepts/streaming)。
## 模型引用
配置中的模型引用(例如 `agents.defaults.model``agents.defaults.models`)通过**第一个** `/` 进行拆分解析。
配置中的模型引用(例如 `agents.defaults.model``agents.defaults.models`)通过**第一个** `/` 处分割来解析。
- 配置模型时使用 `provider/model` 格式
- 如果模型 ID 本身包含 `/`OpenRouter 风格),请包含提供商前缀(例:`openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商,OpenClaw 将输入视为别名或**默认提供商**的模型(仅在模型 ID 中没有 `/` 时有效)。
- 配置模型时使用 `provider/model`
- 如果模型 ID 本身包含 `/`OpenRouter 风格),请包含提供商前缀(例`openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商,OpenClaw 将输入视为别名或**默认提供商**的模型(仅在模型 ID 中没有 `/` 时有效)。
## 配置(最小
## 配置(最小)
至少需要设置:
+49 -49
View File
@@ -1,123 +1,123 @@
---
read_when:
- 处理 Gateway网关协议、客户端或传输层相关工作时
summary: WebSocket Gateway网关架构、组件和客户端流程
title: Gateway网关架构
- 正在开发 Gateway 网关协议、客户端或传输层
summary: WebSocket Gateway 网关架构、组件和客户端流程
title: Gateway 网关架构
x-i18n:
generated_at: "2026-02-01T20:22:27Z"
generated_at: "2026-02-03T07:45:55Z"
model: claude-opus-4-5
provider: pi
source_hash: c636d5d8a5e628067432b30671466309e3d630b106d413f1708765bf2a9399a1
source_path: concepts/architecture.md
workflow: 14
workflow: 15
---
# Gateway网关架构
# Gateway 网关架构
最后更新:2026-01-22
## 概述
- 单个长生命周期的 **Gateway网关** 管理所有消息接入面(通过 Baileys 接入 WhatsApp、通过 grammY 接入 Telegram、Slack、Discord、Signal、iMessage、WebChat)。
- 控制面客户端(macOS 应用、CLI、Web UI、自动化)通过 **WebSocket** 连接到 Gateway网关,使用配置的绑定地址(默认 `127.0.0.1:18789`
- **节点**macOS/iOS/Android/无头模式)也通过 **WebSocket** 连接,但声明 `role: node`显式指定能力/命令。
- 每台主机一个 Gateway网关;它是唯一打开 WhatsApp 会话的位置。
- **画布主机**(默认 `18793`)提供智能体可编辑的 HTML 和 A2UI。
- 单个长期运行的 **Gateway 网关**拥有所有消息平台(通过 Baileys WhatsApp、通过 grammY Telegram、Slack、Discord、Signal、iMessage、WebChat)。
- 控制面客户端(macOS 应用、CLI、Web 界面、自动化)通过配置的绑定主机(默认 `127.0.0.1:18789`)上的 **WebSocket** 连接到 Gateway 网关。
- **节点**macOS/iOS/Android/无头设备)也通过 **WebSocket** 连接,但声明 `role: node`带有明确的能力/命令。
- 每台主机一个 Gateway 网关;它是唯一打开 WhatsApp 会话的位置。
- **canvas 主机**(默认 `18793`)提供智能体可编辑的 HTML 和 A2UI。
## 组件和流程
### Gateway网关(守护进程)
### Gateway 网关(守护进程)
- 维护提供商连接。
- 暴露类型化的 WS API(请求、响应、服务推送事件)。
- 暴露类型化的 WS API(请求、响应、服务推送事件)。
- 根据 JSON Schema 验证入站帧。
- 发出 `agent``chat``presence``health``heartbeat``cron` 等事件
- 发出事件如 `agent``chat``presence``health``heartbeat``cron`
### 客户端(Mac 应用 / CLI / Web 管理
### 客户端(mac 应用 / CLI / web 管理)
- 每个客户端一个 WS 连接。
- 发送请求(`health``status``send``agent``system-presence`)。
- 订阅事件(`tick``agent``presence``shutdown`)。
### 节点(macOS / iOS / Android / 无头模式
### 节点(macOS / iOS / Android / 无头设备
- 连接到**同一个 WS 服务器**,声明 `role: node`
-`connect` 中提供设备身份;配对是**基于设备**的(角色为 `node`),审批信息存储在设备配对存储中。
- 暴露 `canvas.*``camera.*``screen.record``location.get` 等命令
- `role: node` 连接到**同一个 WS 服务器**。
-`connect` 中提供设备身份;配对是**基于设备**的(角色为 `node`),批准存储在设备配对存储中。
- 暴露命令如 `canvas.*``camera.*``screen.record``location.get`
协议详情:
- [Gateway网关协议](/gateway/protocol)
- [Gateway 网关协议](/gateway/protocol)
### WebChat
- 静态 UI,使用 Gateway网关 WS API 获取聊天历史和发送消息。
- 静态界面,使用 Gateway 网关 WS API 获取聊天历史和发送消息。
- 在远程设置中,通过与其他客户端相同的 SSH/Tailscale 隧道连接。
## 连接生命周期(单个客户端)
```
Client Gateway网关
Client Gateway
| |
|---- req:connect -------->|
|<------ res (ok) ---------| (或 res error + 关闭)
| payload=hello-ok 携带快照:presence + health
|<------ res (ok) ---------| (or res error + close)
| (payload=hello-ok carries snapshot: presence + health)
| |
|<------ event:presence ---|
|<------ event:tick -------|
| |
|------- req:agent ------->|
|<------ res:agent --------| (确认:{runId,status:"accepted"}
|<------ event:agent ------| (流式传输)
|<------ res:agent --------| (最终:{runId,status,summary}
|<------ res:agent --------| (ack: {runId,status:"accepted"})
|<------ event:agent ------| (streaming)
|<------ res:agent --------| (final: {runId,status,summary})
| |
```
## 线路协议(摘要)
- 传输WebSocket文本帧携带 JSON 载。
- 传输:WebSocket,带 JSON 载荷的文本帧
- 第一帧**必须**是 `connect`
- 握手完成后:
- 握手后:
- 请求:`{type:"req", id, method, params}``{type:"res", id, ok, payload|error}`
- 事件:`{type:"event", event, payload, seq?, stateVersion?}`
- 如果设置了 `OPENCLAW_GATEWAY_TOKEN`(或 `--token`),`connect.params.auth.token` 必须匹配,否则套接字关闭。
- 有副作用的方法(`send``agent`)需要幂等键以安全重试;服务器维护一个短期去重缓存。
- 如果设置了 `OPENCLAW_GATEWAY_TOKEN`(或 `--token`),`connect.params.auth.token` 必须匹配,否则套接字关闭。
- 有副作用的方法(`send``agent`)需要幂等键以安全重试;服务器保持短期去重缓存。
- 节点必须在 `connect` 中包含 `role: "node"` 以及能力/命令/权限。
## 配对本地信任
## 配对 + 本地信任
- 所有 WS 客户端(操作员 + 节点)在 `connect` 时包含**设备身份**。
- 新设备 ID 需要配对批;Gateway网关颁发**设备令牌**用于后续连接
- **本地**连接(local loopback 或 Gateway网关主机自身的 tailnet 地址)可以自动审批,以保持同主机用户体验流畅
- **非本地**连接必须 `connect.challenge` nonce 签名,并需要显式审批
- Gateway网关认证(`gateway.auth.*`)仍适用于**所有**连接,无论本地还是远程。
- 新设备 ID 需要配对批Gateway 网关为后续连接颁发**设备令牌**。
- **本地**连接(loopback 或 Gateway 网关主机自身的 tailnet 地址)可以自动批准以保持同主机用户体验流畅。
- **非本地**连接必须签名 `connect.challenge` nonce 并需要明确批准
- Gateway 网关认证(`gateway.auth.*`)仍适用于**所有**连接,无论本地还是远程。
详情:[Gateway网关协议](/gateway/protocol)、[配对](/start/pairing)、[安全](/gateway/security)。
详情:[Gateway 网关协议](/gateway/protocol)、[配对](/start/pairing)、[安全](/gateway/security)。
## 协议类型定义与代码生成
## 协议类型代码生成
- TypeBox schema 定义协议。
- 从这些 schema 生成 JSON Schema。
- TypeBox 模式定义协议。
- 从这些模式生成 JSON Schema。
- 从 JSON Schema 生成 Swift 模型。
## 远程访问
- 推荐方式Tailscale 或 VPN。
- 备选方式SSH 隧道
- 推荐:Tailscale 或 VPN。
- 替代方案SSH 隧道
```bash
ssh -N -L 18789:127.0.0.1:18789 user@host
```
- 相同的握手 + 认证令牌适用于隧道连接。
- 远程设置中可为 WS 启用 TLS + 可选的证书固定。
- 远程设置中可为 WS 启用 TLS + 可选的证书固定。
## 运维概览
## 操作快照
- 启动:`openclaw gateway`(前台运行,日志输出到 stdout)。
- 健康检查:通过 WS 发送 `health`(也包含在 `hello-ok` 中)。
-:使用 launchd/systemd 实现自动重启。
- 启动:`openclaw gateway`(前台,日志输出到 stdout)。
- 健康检查:通过 WS `health`(也包含在 `hello-ok` 中)。
-:使用 launchd/systemd 自动重启。
## 不变量
- 每台主机恰好一个 Gateway网关控制单个 Baileys 会话。
- 握手是强制的;任何非 JSON 或非 connect 的首帧将导致硬关闭。
- 每台主机恰好一个 Gateway 网关控制单个 Baileys 会话。
- 握手是强制的;任何非 JSON 或非 connect 的第一帧都会导致硬关闭。
- 事件不会重放;客户端必须在出现间隙时刷新。
+47 -47
View File
@@ -1,40 +1,40 @@
---
read_when:
- 你想了解 OpenClaw 中"上下文"的含义
- 你在调试为什么模型"知道"某些内容(或遗忘了它
- 你在调试为什么模型"知道"某些内容(或忘记了
- 你想减少上下文开销(/context、/status、/compact
summary: 上下文:模型看到的内容、如何构建以及如何检查
title: 上下文
x-i18n:
generated_at: "2026-02-01T20:22:35Z"
generated_at: "2026-02-03T07:46:15Z"
model: claude-opus-4-5
provider: pi
source_hash: b32867b9b93254fdd1077d0d97c203cabfdba3330bb941693c83feba8e5db0cc
source_path: concepts/context.md
workflow: 14
workflow: 15
---
# 上下文
"上下文"是 **OpenClaw 在一次运行中发送给模型的所有内容**。它受模型的**上下文窗口**(token 限制)约束。
初学者心智模型:
新手心智模型:
- **系统提示词**OpenClaw 构建):规则、工具、Skills 列表、时间/运行时信息,以及注入的工作区文件。
- **对话历史**:你的消息 + 助手在本次会话中的消息。
- **系统提示词**(OpenClaw 构建):规则、工具、Skills 列表、时间/运行时,以及注入的工作区文件。
- **对话历史**:你的消息 + 助手在会话中的消息。
- **工具调用/结果 + 附件**:命令输出、文件读取、图片/音频等。
上下文与"记忆"_不是同一回事_:记忆可以存储在磁盘上并在之后重新加载;上下文是当前模型窗口内的内容。
上下文与"记忆"_不是同一回事_:记忆可以存储在磁盘上并后重新加载;上下文是模型当前窗口内的内容。
## 快速开始(检查上下文)
- `/status` → 快速查看"我的窗口还剩多少空间?"以及会话设置。
- `/context list`查看注入了哪些内容及大致大小(按文件和总计)。
- `/context detail` → 更深入的分解:文件、工具 schema 大小、 Skills 条目大小,以及系统提示词大小。
- `/usage tokens` → 在正常回复后附加每次回复的用量信息
- `/compact` → 将较的历史记录总结为一个压缩条目以释放窗口空间。
- `/status` → 快速查看"我的窗口有多满?" + 会话设置。
- `/context list` → 注入了什么 + 大致大小(每个文件 + 总计)。
- `/context detail` → 更深入的分解:每个文件、每个工具 schema 大小、每个 Skills 条目大小系统提示词大小。
- `/usage tokens` → 在正常回复后附加每次回复的使用量页脚
- `/compact` → 将较的历史总结为紧凑条目以释放窗口空间。
另请参阅:[斜杠命令](/tools/slash-commands)、[Token 用量与费用](/token-use)、[压缩](/concepts/compaction)。
另请参阅:[斜杠命令](/tools/slash-commands)、[Token 使用与成本](/token-use)、[压缩](/concepts/compaction)。
## 示例输出
@@ -83,33 +83,33 @@ Top tools (schema size):
… (+N more tools)
```
## 哪些内容计入上下文窗口
## 什么计入上下文窗口
模型接收的所有内容都计入,包括:
模型接收的所有内容都计入,包括:
- 系统提示词(所有部分)。
- 对话历史。
- 工具调用 + 工具结果。
- 附件/转录内容(图片/音频/文件)。
- 附件/转录(图片/音频/文件)。
- 压缩摘要和修剪产物。
- 提供商"包装器"或隐藏头信息(不可见,但仍会计入)。
- 提供商"包装器"或隐藏头(不可见,仍然计数)。
## OpenClaw 如何构建系统提示词
系统提示词由 **OpenClaw 拥有**,每次运行时重新构建。它包括:
系统提示词由 **OpenClaw 拥有**,每次运行时重建。它包括:
- 工具列表 + 简短描述。
- Skills 列表(仅元数据;见下文)。
- 工作区位置。
- 时间(UTC + 如配置则转换为用户时间)。
- 运行时元数据(主机/操作系统/模型/思考模式)。
- **Project Context** 下注入的工作区引导文件。
- 时间(UTC + 如配置则转换为用户时间)。
- 运行时元数据(主机/操作系统/模型/思考)。
-**项目上下文**下注入的工作区引导文件。
完整分解:[系统提示词](/concepts/system-prompt)。
## 注入的工作区文件(Project Context
## 注入的工作区文件(项目上下文
默认情况下,OpenClaw 注入一组固定的工作区文件(如果存在):
默认情况下,OpenClaw 注入一组固定的工作区文件(如果存在):
- `AGENTS.md`
- `SOUL.md`
@@ -119,50 +119,50 @@ Top tools (schema size):
- `HEARTBEAT.md`
- `BOOTSTRAP.md`(仅首次运行)
大文件`agents.defaults.bootstrapMaxChars`(默认 `20000` 字符)逐文件截断。`/context` 显示**原始大小与注入大小**的对比,以及是否发生了截断。
大文件按文件使用 `agents.defaults.bootstrapMaxChars`(默认 `20000` 字符)截断。`/context` 显示**原始 vs 注入**大小以及是否发生了截断。
## Skills:注入的内容按需加载的内容
## Skills:注入的内容 vs 按需加载的内容
系统提示词包含一个紧凑的**Skills 列表**(名称 + 描述 + 位置)。此列表会产生实际开销。
系统提示词包含一个紧凑的 **Skills 列表**(名称 + 描述 + 位置)。此列表实际开销。
Skills 指令默认*不*包含在内。模型应**需要时**`read` Skills`SKILL.md`
Skill 指令默认*不*包含。模型应**仅在需要时**`read` Skill 的 `SKILL.md`
## 工具:两种开销
## 工具:两种成本
工具以两种方式影响上下文:
1. 系统提示词中的**工具列表文本**你看到的"Tooling"部分)。
2. **工具 schema**JSON)。这些发送给模型以便调用工具。即使你看不到它们纯文本形式,它们也会计入上下文
1. 系统提示词中的**工具列表文本**(你看到的"Tooling")。
2. **工具 schema**JSON)。这些发送给模型以便它可以调用工具。它们计入上下文,即使你看不到它们作为纯文本。
`/context detail` 分解最大的工具 schema让你了解哪些占用最多
`/context detail` 分解最大的工具 schema以便你可以看到什么占主导
## 命令、指令和"内联快捷方式"
斜杠命令由 Gateway网关处理。有几种不同的行为:
斜杠命令由 Gateway 网关处理。有几种不同的行为:
- **独立命令**:仅包含 `/...` 的消息作为命令运行。
- **指令**`/think``/verbose``/reasoning``/elevated``/model``/queue` 在模型看到消息之前被移除
-指令消息会持久化会话设置。
- 普通消息中的内联指令作为单次消息提示生效
- **内联快捷方式**(仅限白名单发送者):普通消息中的某些 `/...` 标记可以立即行(例如:"hey /status"),并在模型看到剩余文本之前被移除
- **独立命令**:仅 `/...` 的消息作为命令运行。
- **指令**`/think``/verbose``/reasoning``/elevated``/model``/queue` 在模型看到消息之前被剥离
- 仅指令消息会持久化会话设置。
- 正常消息中的内联指令作为每条消息提示。
- **内联快捷方式**(仅允许列表中的发送者):正常消息中的某些 `/...` token 可以立即行(例如:"hey /status"),并在模型看到剩余文本之前被剥离
详情:[斜杠命令](/tools/slash-commands)。
## 会话、压缩和修剪(哪些内容会持久化)
## 会话、压缩和修剪(什么会持久化)
跨消息持久化的内容取决于机制:
什么在消息之间持久化取决于机制:
- **普通历史**会持久化在会话录中,直到被策略压缩/修剪。
- **压缩**将摘要持久化到录中,并保最近的消息不变。
- **修剪**从运行的*内存中*提示词里移除旧的工具结果,但不重写录。
- **正常历史**在会话录中持久化,直到被策略压缩/修剪。
- **压缩**将摘要持久化到录中,并保最近的消息不变。
- **修剪**从运行的*内存中*提示词中删除旧的工具结果,但不重写录。
文档:[会话](/concepts/session)、[压缩](/concepts/compaction)、[会话修剪](/concepts/session-pruning)。
## `/context` 实际报告的内容
## `/context` 实际报告什么
`/context` 优先使用最新的**运行构建的**系统提示词报告(如果可用)
`/context` 在可用时优先使用最新的**运行构建的**系统提示词报告:
- `System prompt (run)` = 从一次嵌入式(具有工具能力的)运行中捕获,并持久化在会话存储中。
- `System prompt (estimate)` = 当不存在运行报告时(或通过不生成报告的 CLI 后端运行时)即时计算。
- `System prompt (run)` = 从最后一次嵌入式(具有工具能力的)运行中捕获,并持久化在会话存储中。
- `System prompt (estimate)` = 当没有运行报告存在时(或通过不生成报告的 CLI 后端运行时)即时计算。
无论哪种方式,它都报告大小和主要贡献者;它**不会**输出完整的系统提示词或工具 schema。
无论哪种方式,它都报告大小和主要贡献者;它**不会**转储完整的系统提示词或工具 schema。
+28 -28
View File
@@ -1,36 +1,36 @@
---
read_when:
- 更改群组消息规则或提及方式
summary: WhatsApp 群组消息处理的行为配置(mentionPatterns 在各平台间共享)
- 更改群组消息规则或提及设置
summary: WhatsApp 群组消息处理的行为配置(mentionPatterns 在各平台间共享)
title: 群组消息
x-i18n:
generated_at: "2026-02-01T20:22:33Z"
generated_at: "2026-02-03T10:05:00Z"
model: claude-opus-4-5
provider: pi
source_hash: 181a72f12f5021af77c2e4c913120f711e0c0bc271d218d75cb6fe80dab675bb
source_path: concepts/group-messages.md
workflow: 14
workflow: 15
---
# 群组消息(WhatsApp 网页渠道)
目标:让 Clawd 留在 WhatsApp 群组中,仅在被提及时唤醒,并将该线程与个人私会话隔离
目标:让 Clawd 留在 WhatsApp 群组中,仅在被提及时唤醒,并将该对话线程与个人私会话分开
注意:`agents.list[].groupChat.mentionPatterns` 现在也被 Telegram/Discord/Slack/iMessage 使用;本文档重点介绍 WhatsApp 特定的行为。对于多智能体置,为每个智能体设置 `agents.list[].groupChat.mentionPatterns`(或使用 `messages.groupChat.mentionPatterns` 作为全局回退)。
注意:`agents.list[].groupChat.mentionPatterns` 现在也被 Telegram/Discord/Slack/iMessage 使用;本文档重点介绍 WhatsApp 特定的行为。对于多智能体置,为每个智能体设置 `agents.list[].groupChat.mentionPatterns`(或使用 `messages.groupChat.mentionPatterns` 作为全局回退)。
## 已实现的功能(2025-12-03
- 激活模式:`mention`(默认)或 `always``mention` 需要一次提及(通过 `mentionedJids` 实现的 WhatsApp 原生 @提及、正则匹配,或消息文本中包含机器人 E.164 号码)。`always` 会在每条消息时唤醒智能体,但智能体仅在能提供有价值的回复时才会响应;否则返回静默令牌 `NO_REPLY`。默认值可在配置中设置(`channels.whatsapp.groups`),可通过 `/activation` 按群组覆盖。设置 `channels.whatsapp.groups` ,它同时充当群组白名单(添加 `"*"` 以允许所有群组)。
- 群组策略:`channels.whatsapp.groupPolicy` 控制是否接受群组消息(`open|disabled|allowlist`)。`allowlist` 使用 `channels.whatsapp.groupAllowFrom`(回退:显式的 `channels.whatsapp.allowFrom`)。默认为 `allowlist`(在添加发送者之前被阻止)。
- 按群组隔离会话:会话键格式为 `agent:<agentId>:whatsapp:group:<jid>`,因此 `/verbose on``/think high` 等命令(作为独立消息发送)仅作用于该群组;个人私状态不受影响。群组线程会跳过心跳。
- 上下文注入:**仅待处理**群组消息(默认 50 条)——即未触发运行的消息——会以 `[Chat messages since your last reply - for context]` 为前缀注入,触发消息则以 `[Current message - respond to this]` 为前缀。已在会话中的消息不会重复注入。
- 发送者标识:每个群组消息批次末尾会附加 `[from: Sender Name (+E164)]`,以便 Pi 知道发言者是谁。
- 阅后即焚/一次性查看消息:我们在提取文本/提及之前先解包这些消息,因此其中的提及仍会触发。
- 群组系统提示:在群组会话的第一轮(以及每次通过 `/activation` 更改模式时),我们会系统提示词中注入一段简短说明,`You are replying inside the WhatsApp group "<subject>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` 如果元数据不可用,我们仍会告知智能体这是一个群聊。
- 激活模式:`mention`(默认)或 `always``mention` 需要提及(通过 `mentionedJids`真实 WhatsApp @提及、正则表达式模式,或文本中任意位置的机器人 E.164 号码)。`always` 会在每条消息时唤醒智能体,但它应该只在能提供有意义价值时才回复;否则返回静默令牌 `NO_REPLY`。默认值可在配置中设置(`channels.whatsapp.groups`),可通过 `/activation` 为每个群组单独覆盖。设置 `channels.whatsapp.groups` ,它同时充当群组允许列表(包含 `"*"` 以允许所有群组)。
- 群组策略:`channels.whatsapp.groupPolicy` 控制是否接受群组消息(`open|disabled|allowlist`)。`allowlist` 使用 `channels.whatsapp.groupAllowFrom`(回退:显式的 `channels.whatsapp.allowFrom`)。默认为 `allowlist`(在添加发送者之前被阻止)。
- 独立群组会话:会话键格式为 `agent:<agentId>:whatsapp:group:<jid>`,因此 `/verbose on``/think high`(作为独立消息发送)等命令仅作用于该群组;个人私状态不受影响。群组线程会跳过心跳。
- 上下文注入:**仅待处理**群组消息(默认 50 条),即*未*触发运行的消息会以 `[Chat messages since your last reply - for context]` 为前缀注入,触发行在 `[Current message - respond to this]` 。已在会话中的消息不会重复注入。
- 发送者显示:每个群组批次现在以 `[from: Sender Name (+E164)]` 结尾,让 Pi 知道是谁在说话
- 阅后即焚/一次性查看:我们在提取文本/提及之前先解包这些消息,因此其中的提及仍会触发。
- 群组系统提示:在群组会话的第一轮(以及每 `/activation` 更改模式时),我们会系统提示注入一段简短说明,如 `You are replying inside the WhatsApp group "<subject>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` 如果元数据不可用,我们仍会告知智能体这是一个群聊。
## 配置示例(WhatsApp
`~/.openclaw/openclaw.json` 中添加 `groupChat` 块,以便在 WhatsApp 去除文本正文中可见`@` 时,显示名称提及仍然有效
`~/.openclaw/openclaw.json` 中添加 `groupChat` 块,以便在 WhatsApp 剥离文本正文中的可视 `@` 时,显示名称提及仍能正常工作
```json5
{
@@ -55,37 +55,37 @@ x-i18n:
}
```
说明
注意
- 正则表达式不区分大小写;它们涵盖了 `@openclaw` 这样的显示名称提及,以及带或不带 `+`/空格的原始号码。
-用户点击联系人时,WhatsApp 仍会通过 `mentionedJids` 发送规范提及,因此号码回退方式很少需要,但作为安全保障很有用。
- 正则表达式不区分大小写;它们涵盖了 `@openclaw` 这样的显示名称提及,以及带或不带 `+`/空格的原始号码。
-有人点击联系人时,WhatsApp 仍会通过 `mentionedJids` 发送规范提及,因此号码回退很少需要,但作为安全很有用。
### 激活命令(仅所有者)
### 激活命令(仅所有者)
使用群聊命令:
- `/activation mention`
- `/activation always`
只有所有者号码(来自 `channels.whatsapp.allowFrom`,未设置时使用机器人自的 E.164 号码)可以更改此设置。在群组中发送 `/status` 作为独立消息即可查看当前激活模式。
只有所有者号码(来自 `channels.whatsapp.allowFrom`未设置时使用机器人自的 E.164)可以更改此设置。在群组中发送 `/status` 作为独立消息查看当前激活模式。
## 使用方法
1. 将你的 WhatsApp 账号(运行 OpenClaw 的账号)添加到群组。
2. 发送 `@openclaw …`(或包含号码)。除非设置 `groupPolicy: "open"`,否则只有白名单中的发送者才能触发
3. 智能体提示将包含最近的群组上下文以及尾的 `[from: …]` 标记,以便它能回复正确的人。
4. 会话级指令(`/verbose on``/think high``/new``/reset``/compact`)仅适用于该群组的会话;将它们作为独立消息发送以确保生效。你的个人私会话保持独立。
2. `@openclaw …`(或包含号码)。只有允许列表中的发送者才能触发,除非设置 `groupPolicy: "open"`
3. 智能体提示将包含最近的群组上下文以及尾`[from: …]` 标记,以便它能够回应正确的人。
4. 会话级指令(`/verbose on``/think high``/new``/reset``/compact`)仅适用于该群组的会话;将它们作为独立消息发送以使其生效。你的个人私会话保持独立。
## 测试 / 验证
## 测试/验证
- 手动冒烟测试:
- 在群组中发送 `@openclaw` 提及,确认回复中引用发送者名称。
- 再次发送提及,验证历史消息块已包含并在下一轮清除。
- 检查 Gateway网关日志(使用 `--verbose` 运行)查看 `inbound web message` 条目,确认其显示 `from: <groupJid>``[from: …]` 后缀。
- 在群组中发送 `@openclaw` 提及,确认收到引用发送者名称的回复
- 发送第二次提及,验证历史记录块被包含,然后在下一轮清除。
- 检查 Gateway 网关日志(使用 `--verbose` 运行)查看 `inbound web message` 条目,显示 `from: <groupJid>``[from: …]` 后缀。
## 已知注意事项
- 群组有意跳过心跳以避免嘈杂的广播。
- 回声抑制使用组合的批次字符串;如果你在没有提及的情况下发送两次相同文本,只有第一次会到响应。
- 会话存储条目将 `agent:<agentId>:whatsapp:group:<jid>` 的形式出现在会话存储中(默认为 `~/.openclaw/agents/<agentId>/sessions/sessions.json`);缺条目仅表示该群组尚未触发运行。
- 回声抑制使用组合的批次字符串;如果你发送两次相同文本但没有提及,只有第一次会到响应。
- 会话存储条目将在会话存储中显示为 `agent:<agentId>:whatsapp:group:<jid>`(默认为 `~/.openclaw/agents/<agentId>/sessions/sessions.json`);缺条目只是意味着该群组尚未触发运行。
- 群组中的输入指示器遵循 `agents.defaults.typingMode`(默认:未被提及时为 `message`)。
+73 -74
View File
@@ -1,54 +1,53 @@
---
read_when:
- 更改群聊行为或提及门控
- 更改群聊行为或提及限制
summary: 跨平台的群聊行为(WhatsApp/Telegram/Discord/Slack/Signal/iMessage/Microsoft Teams
title: 群组
x-i18n:
generated_at: "2026-02-01T20:23:08Z"
generated_at: "2026-02-03T07:47:08Z"
model: claude-opus-4-5
provider: pi
source_hash: b727a053edf51f6e7b5c0c324c2fc9c9789a9796c37f622418bd555e8b5a0ec4
source_path: concepts/groups.md
workflow: 14
workflow: 15
---
# 群组
OpenClaw 在各平台上统一处理群聊:WhatsApp、Telegram、Discord、Slack、Signal、iMessage、Microsoft Teams。
## 入门简介2 分钟)
## 新手入门(2 分钟)
OpenClaw "运行"在你自己的消息账户上。没有单独的 WhatsApp 机器人用户。
如果**你**在某个群组中,OpenClaw 就能看到该群组并在其中回复。
OpenClaw"运行"在你自己的消息账户上。没有单独的 WhatsApp 机器人用户。如果**你**在一个群组中,OpenClaw 就可以看到该群组并在其中回复。
默认行为:
- 群组受限(`groupPolicy: "allowlist"`)。
- 除非你显式禁用提及门控,否则回复需要 @提及
- 除非你明确禁用提及限制,否则回复需要 @ 提及。
含义:允许列表中的发送者可以通过提及 OpenClaw 来触发它
解释:允许列表中的发送者可以通过提及来触发 OpenClaw。
> 简而言之
>
> - **私访问**由 `*.allowFrom` 控制。
> - **私访问**由 `*.allowFrom` 控制。
> - **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。
> - **回复触发**由提及门控`requireMention`、`/activation`)控制。
> - **回复触发**由提及限制`requireMention`、`/activation`)控制。
快速流程(群消息的处理过程):
快速流程(群消息会发生什么):
```
groupPolicy? disabled -> drop
groupPolicy? allowlist -> group allowed? no -> drop
requireMention? yes -> mentioned? no -> store for context only
otherwise -> reply
groupPolicy? disabled -> 丢弃
groupPolicy? allowlist -> 群组允许? 否 -> 丢弃
requireMention? -> 被提及? 否 -> 仅存储为上下文
否则 -> 回复
```
![群消息流程](/images/groups-flow.svg)
如果你想...
| 目标 | 需要设置的内容 |
如果你想...
| 目标 | 设置什么 |
|------|-------------|
| 允许所有群组但仅在 @提及时回复 | `groups: { "*": { requireMention: true } }` |
| 允许所有群组但仅在 @ 提及时回复 | `groups: { "*": { requireMention: true } }` |
| 禁用所有群组回复 | `groupPolicy: "disabled"` |
| 仅特定群组 | `groups: { "<group-id>": { ... } }`(无 `"*"` 键) |
| 仅你可以在群组中触发 | `groupPolicy: "allowlist"``groupAllowFrom: ["+1555..."]` |
@@ -56,32 +55,32 @@ otherwise -> reply
## 会话键
- 群组会话使用 `agent:<agentId>:<channel>:group:<id>` 会话键(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
- Telegram 论坛主题会在群组 ID 后`:topic:<threadId>`使每个主题拥有独立的会话。
- 私聊使用主会话(或按发送者分配,如已配置)。
- 群组会话跳过心跳检测
- Telegram 论坛话题在群组 ID 后`:topic:<threadId>`因此每个话题都有自己的会话。
- 私聊使用主会话(或按发送者配置时使用各自的会话)。
- 群组会话跳过心跳。
## 模式:个人私 + 公开群组(单智能体)
## 模式:个人私 + 公开群组(单智能体)
可以——如果你的"个人"流量是**私**"公开"流量是**群组**,这种方式效果很好。
是的——如果你的"个人"流量是**私**"公开"流量是**群组**,这种方式效果很好。
原因:在单智能体模式下,私通常落在**主**会话键(`agent:main:main`,而群组始终使用**非主**会话键(`agent:main:<channel>:group:<id>`)。如果你启用沙箱并设置 `mode: "non-main"`,这些群组会话在 Docker 中运行,而你的主私会话在主机上。
原因:在单智能体模式下,私通常落在**主**会话键(`agent:main:main`,而群组始终使用**非主**会话键(`agent:main:<channel>:group:<id>`)。如果你启用 `mode: "non-main"` 的沙箱隔离,这些群组会话在 Docker 中运行,而你的主私会话保持在主机上。
为你提供了一个智能体"大脑"(共享工作区 + 记忆),但两种执行姿态:
给你一个智能体"大脑"(共享工作区 + 记忆),但两种执行姿态:
- **私**:完整工具(主机)
- **私**:完整工具(主机)
- **群组**:沙箱 + 受限工具(Docker)
> 如果你需要真正独立的工作区/角色("个人"和"公开"绝不能混合),请使用第二个智能体 + 绑定。参见[多智能体路由](/concepts/multi-agent)。
示例(私在主机上,群组沙箱隔离 + 仅消息工具):
示例(私在主机上,群组沙箱隔离 + 仅消息工具):
```json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // groups/channels are non-main -> sandboxed
scope: "session", // strongest isolation (one container per group/channel)
mode: "non-main", // 群组/频道是非主 -> 沙箱隔离
scope: "session", // 最强隔离(每个群组/频道一个容器)
workspaceAccess: "none",
},
},
@@ -89,7 +88,7 @@ otherwise -> reply
tools: {
sandbox: {
tools: {
// If allow is non-empty, everything else is blocked (deny still wins).
// 如果 allow 非空,其他所有工具都被阻止(deny 仍然优先)。
allow: ["group:messaging", "group:sessions"],
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
},
@@ -98,7 +97,7 @@ otherwise -> reply
}
```
想要"群组只能访问文件夹 X"而不是"无主机访问"?保持 `workspaceAccess: "none"` 并仅将允许的路径挂载到沙箱中:
想要"群组只能看到文件夹 X"而不是"无主机访问"?保持 `workspaceAccess: "none"` 并仅将允许的路径挂载到沙箱中:
```json5
{
@@ -120,20 +119,20 @@ otherwise -> reply
}
```
相关内容
相关:
- 配置键和默认值:[Gateway网关配置](/gateway/configuration#agentsdefaultssandbox)
- 调试工具被阻止的原因[沙箱 vs 工具策略 vs 提权](/gateway/sandbox-vs-tool-policy-vs-elevated)
- 配置键和默认值:[Gateway 网关配置](/gateway/configuration#agentsdefaultssandbox)
- 调试为什么工具被阻止:[沙箱 vs 工具策略 vs 提权](/gateway/sandbox-vs-tool-policy-vs-elevated)
- 绑定挂载详情:[沙箱隔离](/gateway/sandboxing#custom-bind-mounts)
## 显示标签
- UI 标签在可用时使用 `displayName`,格式为 `<channel>:<token>`
- `#room` 保留房间/频道;群聊使用 `g-<slug>`(小写,空格转为 `-`,保留 `#@+._-`)。
- `#room` 保留用于房间/频道;群聊使用 `g-<slug>`(小写,空格 -> `-`,保留 `#@+._-`)。
## 群组策略
按渠道控制群组/房间消息的处理方式
控制每个渠道如何处理群组/房间消息:
```json5
{
@@ -180,34 +179,34 @@ otherwise -> reply
}
```
| 策略 | 行为 |
| ------------- | ------------------------------------- |
| `"open"` | 群组绕过允许列表;提及门控仍然适用。 |
| `"disabled"` | 完全阻止所有群组消息。 |
| `"allowlist"` | 仅允许匹配已配置允许列表的群组/房间。 |
| 策略 | 行为 |
| ------------- | --------------------------------------- |
| `"open"` | 群组绕过允许列表;提及限制仍然适用。 |
| `"disabled"` | 完全阻止所有群组消息。 |
| `"allowlist"` | 仅允许配置允许列表匹配的群组/房间。 |
注意事项:
- `groupPolicy` 与提及门控(要求 @提及)是分开的。
- `groupPolicy` 与提及限制(需要 @ 提及)是分开的。
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams:使用 `groupAllowFrom`(回退:显式 `allowFrom`)。
- Discord:允许列表使用 `channels.discord.guilds.<id>.channels`
- Slack:允许列表使用 `channels.slack.channels`
- Matrix:允许列表使用 `channels.matrix.groups`(房间 ID、别名或名称)。使用 `channels.matrix.groupAllowFrom` 限制发送者;也支持房间的 `users` 允许列表。
- 群组私单独控制(`channels.discord.dm.*``channels.slack.dm.*`)。
- Matrix:允许列表使用 `channels.matrix.groups`(房间 ID、别名或名称)。使用 `channels.matrix.groupAllowFrom` 限制发送者;也支持每个房间的 `users` 允许列表。
- 群组私单独控制(`channels.discord.dm.*``channels.slack.dm.*`)。
- Telegram 允许列表可以匹配用户 ID(`"123456789"``"telegram:123456789"``"tg:123456789"`)或用户名(`"@alice"``"alice"`);前缀不区分大小写。
- 默认为 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息将被阻止。
快速心智模型(群消息的评估顺序):
快速心智模型(群消息的评估顺序):
1. `groupPolicy`open/disabled/allowlist
2. 群组允许列表(`*.groups``*.groupAllowFrom`、渠道特定允许列表)
3. 提及门控`requireMention``/activation`
2. 群组允许列表(`*.groups``*.groupAllowFrom`、渠道特定允许列表)
3. 提及限制`requireMention``/activation`
## 提及门控(默认)
## 提及限制(默认)
群消息需要提及才能触发,除非按群组覆盖。默认值位于 `*.groups."*"` 下的子系统中。
消息需要提及,除非按群组覆盖。默认值位于 `*.groups."*"` 下的每个子系统中。
回复机器人消息视为隐式提及(当渠道支持回复元数据时)。这适用于 Telegram、WhatsApp、Slack、Discord 和 Microsoft Teams。
回复机器人消息视为隐式提及(当渠道支持回复元数据时)。这适用于 Telegram、WhatsApp、Slack、Discord 和 Microsoft Teams。
```json5
{
@@ -248,18 +247,18 @@ otherwise -> reply
注意事项:
- `mentionPatterns` 是不区分大小写的正则表达式。
- 提供原生提及的平台仍然通过;模式匹配是备用方案
- 智能体覆盖:`agents.list[].groupChat.mentionPatterns`(多个智能体共享一个群组时有用)。
- 提及门控仅在可以检测提及时生效(原生提及或已配置 `mentionPatterns`)。
- Discord 默认值位于 `channels.discord.guilds."*"`(可按服务器/频道覆盖)。
- 群组历史上下文在渠道统一包装,且为**仅待处理**因提及门控跳过的消息);使用 `messages.groupChat.historyLimit` 设置全局默认值,使用 `channels.<channel>.historyLimit`(或 `channels.<channel>.accounts.*.historyLimit`)进行覆盖。设 `0` 以禁用。
- 提供显式提及的平台仍然通过;模式是回退
- 每个智能体覆盖:`agents.list[].groupChat.mentionPatterns`多个智能体共享一个群组时有用)。
- 提及限制仅在提及检测可行时强制执行(原生提及或 `mentionPatterns` 已配置)。
- Discord 默认值位于 `channels.discord.guilds."*"`(可按服务器/频道覆盖)。
- 群组历史上下文在渠道统一包装,并且是**仅待处理**由于提及限制而跳过的消息);使用 `messages.groupChat.historyLimit` 作为全局默认值,使用 `channels.<channel>.historyLimit`(或 `channels.<channel>.accounts.*.historyLimit`)进行覆盖。设 `0` 以禁用。
## 群组/频道工具限制(可选)
某些渠道配置支持限制**特定群组/房间/频道内**可用的工具。
- `tools`:为整个群组允许/拒绝工具。
- `toolsBySender`:群组内按发送者覆盖(键发送者 ID/用户名/邮箱/电话号码,取决于渠道)。使用 `"*"` 作为通配符。
- `toolsBySender`:群组内按发送者覆盖(键发送者 ID/用户名/邮箱/电话号码,取决于渠道)。使用 `"*"` 作为通配符。
解析顺序(最具体的优先):
@@ -290,14 +289,14 @@ otherwise -> reply
注意事项:
- 群组/频道工具限制在全局/智能体工具策略之额外应用(拒绝仍然优先)。
- 某些渠道对房间/频道使用不同的嵌套结构(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。
- 群组/频道工具限制在全局/智能体工具策略之额外应用(deny 仍然优先)。
- 某些渠道对房间/频道使用不同的嵌套结构(例如Discord `guilds.*.channels.*`、Slack `channels.*`、MS Teams `teams.*.channels.*`)。
## 群组允许列表
当配置了 `channels.whatsapp.groups``channels.telegram.groups``channels.imessage.groups` 时,键充当群组允许列表。使用 `"*"` 允许所有群组,同时仍设置默认提及行为。
当配置了 `channels.whatsapp.groups``channels.telegram.groups``channels.imessage.groups` 时,键作为群组允许列表。使用 `"*"` 允许所有群组,同时仍设置默认提及行为。
常见意图(可直接复制粘贴):
常见意图(复制/粘贴):
1. 禁用所有群组回复
@@ -322,7 +321,7 @@ otherwise -> reply
}
```
3. 允许所有群组但要提及(显式)
3. 允许所有群组但要提及(显式)
```json5
{
@@ -350,31 +349,31 @@ otherwise -> reply
## 激活(仅所有者)
群组所有者可以切换群组的激活方式
群组所有者可以切换每个群组的激活状态
- `/activation mention`
- `/activation always`
所有者由 `channels.whatsapp.allowFrom` 确定(未设置时使用机器人自身的 E.164 号码)。以独立消息发送该命令。其他平台目前忽略 `/activation`
所有者由 `channels.whatsapp.allowFrom` 确定(未设置时机器人自身的 E.164)。将命令作为独立消息发送。其他平台目前忽略 `/activation`
## 上下文字段
群组入站消息负载设置:
群组入站负载设置:
- `ChatType=group`
- `GroupSubject`(如已知)
- `GroupMembers`(如已知)
- `WasMentioned`(提及门控结果)
- Telegram 论坛题还包 `MessageThreadId``IsForum`
- `GroupSubject`(如已知)
- `GroupMembers`(如已知)
- `WasMentioned`(提及限制结果)
- Telegram 论坛题还包 `MessageThreadId``IsForum`
智能体系统提示在新群组会话的轮包含群组介。它提醒模型像人一样回复,避免 Markdown 表格,避免输入字面 `\n` 序列。
智能体系统提示在新群组会话的第一轮包含群组介。它提醒模型像人一样回复,避免 Markdown 表格,避免输入字面 `\n` 序列。
## iMessage 特定说明
## iMessage 特定内容
- 路由或添加允许列表时优先使用 `chat_id:<id>`
- 路由或允许列表时优先使用 `chat_id:<id>`
- 列出聊天:`imsg chats --limit 20`
- 群组回复始终返回到同一个 `chat_id`
- 群组回复始终返回到相同的 `chat_id`
## WhatsApp 特定说明
## WhatsApp 特定内容
有关 WhatsApp 专有行为(历史注入、提及处理详情),请参阅[群消息](/concepts/group-messages)。
参见[群消息](/concepts/group-messages)了解 WhatsApp 专有行为(历史注入、提及处理详情)
+87 -84
View File
@@ -1,48 +1,48 @@
---
read_when:
- 想了解记忆文件布局和工作流程
- 想调整自动压缩记忆刷
summary: OpenClaw 记忆的工作原理(工作文件 + 自动记忆刷
- 想了解记忆文件布局和工作流程
- 想调整自动压缩前的记忆刷
summary: OpenClaw 记忆的工作原理(工作空间文件 + 自动记忆刷
title: 记忆
x-i18n:
generated_at: "2026-02-01T20:24:01Z"
generated_at: "2026-02-03T07:47:38Z"
model: claude-opus-4-5
provider: pi
source_hash: f3a7f5d9f61f9742eb3a8adbc3ccaddeadb7e48ceccdfb595327d6d1f55cd00e
source_path: concepts/memory.md
workflow: 14
workflow: 15
---
# 记忆
OpenClaw 记忆是**智能体工作中的纯 Markdown 文件**。这些文件是唯一的事实来源;模型只"记住"写入磁盘的内容。
OpenClaw 记忆是**智能体工作空间中的纯 Markdown 文件**。这些文件是唯一的事实来源;模型只"记住"写入磁盘的内容。
记忆搜索工具由活的记忆插件提供(默认:`memory-core`)。通过 `plugins.slots.memory = "none"` 禁用记忆插件。
记忆搜索工具由活的记忆插件提供(默认:`memory-core`)。使用 `plugins.slots.memory = "none"` 禁用记忆插件。
## 记忆文件(Markdown
默认工作布局使用两个记忆层:
默认工作空间布局使用两个记忆层:
- `memory/YYYY-MM-DD.md`
- 每日日志(仅追加)。
- 会话开始时读取今天和昨天的内容。
- 会话开始时读取今天和昨天的内容。
- `MEMORY.md`(可选)
- 精心整理的长期记忆。
- **仅在主要的私人会话中加载**(不在群组上下文中加载)。
- **仅在主要的私人会话中加载**不在群组上下文中加载)。
这些文件位于工作区目录下(`agents.defaults.workspace`,默认 `~/.openclaw/workspace`)。完整布局参见[智能体工作](/concepts/agent-workspace)。
这些文件位于工作空间下(`agents.defaults.workspace`,默认 `~/.openclaw/workspace`)。完整布局参见[智能体工作空间](/concepts/agent-workspace)。
## 何时写入记忆
- 决策、偏好和持久性事实写入 `MEMORY.md`
- 日常笔记和运行上下文写入 `memory/YYYY-MM-DD.md`
- 如果有人说"记住这个",就写下来(不要只保在内存中)。
- 这个领域仍在发展中。提醒模型存储记忆会有帮助;它知道该怎么做。
- 如果你想让某些信息持久保**机器人把它写入**记忆。
- 如果有人说"记住这个",就写下来(不要只保在内存中)。
- 这个领域仍在发展中。提醒模型存储记忆会有帮助;它知道该怎么做。
- 如果你想让某些内容持久保**请要求机器人将其写入**记忆。
## 自动记忆刷写(预压缩 ping
## 自动记忆刷新(压缩前触发
当会话**接近自动压缩**时,OpenClaw 会触发一个**静默的智能体轮次**,提醒模型在上下文被压缩**之前**写入持久记忆。默认提示明确表示模型*可以回复*,但通常 `NO_REPLY` 是正确的响应,这样用户不会看到这个轮次
当会话**接近自动压缩**时,OpenClaw 会触发一个**静默的智能体回合**,提醒模型在上下文被压缩**之前**写入持久记忆。默认提示明确说明模型*可以回复*,但通常 `NO_REPLY` 是正确的响应,因此用户永远不会看到这个回合
这由 `agents.defaults.compaction.memoryFlush` 控制:
@@ -66,35 +66,35 @@ OpenClaw 的记忆是**智能体工作区中的纯 Markdown 文件**。这些文
详情:
- **软阈值**:当会话 token 估计超过 `contextWindow - reserveTokensFloor - softThresholdTokens` 时触发刷
- 默认**静默**:提示包含 `NO_REPLY`,因此不会传递任何内容。
- **两个提示**:一个用户提示加一个系统提示附加提醒。
- **每个压缩周期刷一次**(在 `sessions.json` 中跟踪)。
- **工作必须可写**:如果会话以 `workspaceAccess: "ro"``"none"` 在沙箱中运行,则跳过刷
- **软阈值**:当会话 token 估计超过 `contextWindow - reserveTokensFloor - softThresholdTokens` 时触发刷
- 默认**静默**:提示包含 `NO_REPLY`,因此不会发送任何内容。
- **两个提示**:一个用户提示加一个系统提示附加提醒。
- **每个压缩周期刷一次**(在 `sessions.json` 中跟踪)。
- **工作空间必须可写**:如果会话以 `workspaceAccess: "ro"``"none"` 在沙箱中运行,则跳过刷
完整的压缩生命周期参见[会话管理 + 压缩](/reference/session-management-compaction)。
## 向量记忆搜索
OpenClaw 可以 `MEMORY.md``memory/*.md`(以及你选择加入的任何额外目录或文件)构建小型向量索引,这样即使措辞不同,语义查询也能找到相关笔记。
OpenClaw 可以 `MEMORY.md``memory/*.md`(以及你选择加入的任何额外目录或文件)构建小型向量索引,以便语义查询可以找到相关笔记,即使措辞不同
默认设置
默认
- 默认启用。
- 监视记忆文件变更(带防抖)。
- 默认使用远程嵌入。如果未设置 `memorySearch.provider`OpenClaw 自动选择:
- 监视记忆文件的更改(去抖动)。
- 默认使用远程嵌入。如果未设置 `memorySearch.provider`OpenClaw 自动选择:
1. 如果配置了 `memorySearch.local.modelPath` 且文件存在,则使用 `local`
2. 如果可以解析 OpenAI 密钥,则使用 `openai`
3. 如果可以解析 Gemini 密钥,则使用 `gemini`
4. 否则记忆搜索保持禁用,直到完成配置
2. 如果可以解析 OpenAI 密钥,则使用 `openai`
3. 如果可以解析 Gemini 密钥,则使用 `gemini`
4. 否则记忆搜索保持禁用状态直到配置完成
- 本地模式使用 node-llama-cpp,可能需要运行 `pnpm approve-builds`
- 使用 sqlite-vec可用时)加速 SQLite 内的向量搜索。
- 使用 sqlite-vec如果可用)在 SQLite 中加速向量搜索。
远程嵌入**需要**嵌入提供商的 API 密钥。OpenClaw 从证配置文件、`models.providers.*.apiKey` 或环境变量解析密钥。Codex OAuth 仅覆盖 chat/completions**不满足**记忆搜索的嵌入需求。对于 Gemini,使用 `GEMINI_API_KEY``models.providers.google.apiKey`。使用自定义 OpenAI 兼容端点时,设置 `memorySearch.remote.apiKey`(以及可选的 `memorySearch.remote.headers`)。
远程嵌入**需要**嵌入提供商的 API 密钥。OpenClaw 从身份验证配置文件、`models.providers.*.apiKey` 或环境变量解析密钥。Codex OAuth 仅涵盖聊天/补全,**不**满足记忆搜索的嵌入需求。对于 Gemini,使用 `GEMINI_API_KEY``models.providers.google.apiKey`。使用自定义 OpenAI 兼容端点时,设置 `memorySearch.remote.apiKey`(以及可选的 `memorySearch.remote.headers`)。
### 额外记忆路径
如果你想索引默认工作布局之外的 Markdown 文件,添加显式路径:
如果你想索引默认工作空间布局之外的 Markdown 文件,添加显式路径:
```json5
agents: {
@@ -106,12 +106,12 @@ agents: {
}
```
注意事项
说明
- 路径可以是绝对路径或工作相对路径。
- 路径可以是绝对路径或工作空间相对路径。
- 目录会递归扫描 `.md` 文件。
- 仅索引 Markdown 文件。
- 符号链接被忽略(文件或目录)。
- 符号链接被忽略(文件或目录)。
### Gemini 嵌入(原生)
@@ -131,13 +131,13 @@ agents: {
}
```
注意事项
说明
- `remote.baseUrl` 是可选的(默认为 Gemini API 基础 URL)。
- `remote.headers` 允许你在需要时添加额外的请求头。
- `remote.headers` 让你可以在需要时添加额外的头。
- 默认模型:`gemini-embedding-001`
如果你想使用**自定义 OpenAI 兼容端点**OpenRouter、vLLM 或代理),可以在 OpenAI 提供商下使用 `remote` 配置:
如果你想使用**自定义 OpenAI 兼容端点**OpenRouter、vLLM 或代理),可以使用 `remote` 配置与 OpenAI 提供商
```json5
agents: {
@@ -157,23 +157,23 @@ agents: {
如果你不想设置 API 密钥,使用 `memorySearch.provider = "local"` 或设置 `memorySearch.fallback = "none"`
回退策略
回退:
- `memorySearch.fallback` 可以是 `openai``gemini``local``none`
- 回退提供商仅在主嵌入提供商失败时使用。
批量索引(OpenAI + Gemini):
- OpenAI 和 Gemini 嵌入默认启用批量索引。设置 `agents.defaults.memorySearch.remote.batch.enabled = false` 禁用。
- 默认行为等待批完成;如需调整,请调节 `remote.batch.wait``remote.batch.pollIntervalMs``remote.batch.timeoutMinutes`
- 设置 `remote.batch.concurrency` 控制并行提交的批量作业(默认:2)。
-模式在 `memorySearch.provider = "openai"``"gemini"` 时适用,并使用相应的 API 密钥。
- Gemini 批作业使用异步嵌入批端点,需要 Gemini Batch API 可用。
- OpenAI 和 Gemini 嵌入默认启用。设置 `agents.defaults.memorySearch.remote.batch.enabled = false` 禁用。
- 默认行为等待批处理完成;如果需要可以调整 `remote.batch.wait``remote.batch.pollIntervalMs``remote.batch.timeoutMinutes`
- 设置 `remote.batch.concurrency` 控制我们并行提交多少个批处理作业(默认:2)。
-处理模式在 `memorySearch.provider = "openai"``"gemini"` 时适用,并使用相应的 API 密钥。
- Gemini 批处理作业使用异步嵌入批处理端点,需要 Gemini Batch API 可用。
为什么 OpenAI 批量又快又便宜:
为什么 OpenAI 批处理快速又便宜:
- 对于大规模回填,OpenAI 通常是我们支持的最快选项,因为我们可以在单个批作业中提交多嵌入请求,让 OpenAI 异步处理。
- OpenAI 为 Batch API 工作负载提供折扣定价,因此大规模索引运行通常比同步发送相同请求更便宜。
- 对于大回填,OpenAI 通常是我们支持的最快选项,因为我们可以在单个批处理作业中提交多嵌入请求,让 OpenAI 异步处理它们
- OpenAI 为 Batch API 工作负载提供折扣定价,因此大索引运行通常比同步发送相同请求更便宜。
- 详情参见 OpenAI Batch API 文档和定价:
- https://platform.openai.com/docs/api-reference/batch
- https://platform.openai.com/pricing
@@ -198,7 +198,7 @@ agents: {
工具:
- `memory_search` — 返回包含文件路径和行范围的片段。
- `memory_search` — 返回带有文件 + 行范围的片段。
- `memory_get` — 按路径读取记忆文件内容。
本地模式:
@@ -209,65 +209,67 @@ agents: {
### 记忆工具的工作原理
- `memory_search` 对来自 `MEMORY.md` + `memory/**/*.md` Markdown 块(约 400 token 目标80 token 重叠)进行语义搜索。返回片段文本(上限约 700 字符)、文件路径、行范围、分数、提供商/模型,以及是否从本地回退到远程嵌入。不返回完整文件内容。
- `memory_get` 读取特定的记忆 Markdown 文件(工作相对路径),可选从起始行读取 N 行。`MEMORY.md` / `memory/` 之外的路径仅在 `memorySearch.extraPaths`显式列出时才允许访问
- 两个工具仅在 `memorySearch.enabled` 对智能体解析为 true 时启用。
- `memory_search` `MEMORY.md` + `memory/**/*.md` 语义搜索 Markdown 块(目标约 400 token80 token 重叠)。返回片段文本(上限约 700 字符)、文件路径、行范围、分数、提供商/模型,以及我们是否从本地回退到远程嵌入。不返回完整文件内容。
- `memory_get` 读取特定的记忆 Markdown 文件(工作空间相对路径),可选从起始行开始读取 N 行。`MEMORY.md` / `memory/` 之外的路径仅在明确列在 `memorySearch.extraPaths` 中时才允许。
- 两个工具仅在智能体的 `memorySearch.enabled` 解析为 true 时启用。
### 索引内容(及时机)
- 文件类型:仅 Markdown`MEMORY.md``memory/**/*.md`,以及 `memorySearch.extraPaths` 下的任何 `.md` 文件)。
- 索引存储:每个智能体的 SQLite 位于 `~/.openclaw/memory/<agentId>.sqlite`(可通过 `agents.defaults.memorySearch.store.path` 配置,支持 `{agentId}` 占位符)。
- 时效性:监视 `MEMORY.md``memory/``memorySearch.extraPaths` 的变更并标记索引为脏(防抖 1.5 秒)。同步在会话开始时、搜索时或按间隔调度,并异步运行。会话记录使用增量阈值触发后台同步。
- 重新索引触发条件:索引存储嵌入的**提供商/模型 + 端点指纹 + 分块参数**。如果其中任何一发生变化,OpenClaw 会自动重置并重新索引整个存储。
- 索引存储:每个智能体的 SQLite 位于 `~/.openclaw/memory/<agentId>.sqlite`(可通过 `agents.defaults.memorySearch.store.path` 配置,支持 `{agentId}` 令牌)。
- 新鲜度:监视器监视 `MEMORY.md``memory/``memorySearch.extraPaths`标记索引为脏(去抖动 1.5 秒)。同步在会话开始时、搜索时或按间隔安排,并异步运行。会话记录使用增量阈值触发后台同步。
- 重新索引触发:索引存储嵌入的**提供商/模型 + 端点指纹 + 分块参数**。如果其中任何一发生变化,OpenClaw 会自动重置并重新索引整个存储。
### 混合搜索(BM25 + 向量)
启用OpenClaw 结合以下两种方式
启用OpenClaw 结合:
- **向量相似度**(语义匹配,措辞可以不同)
- **BM25 关键词相关性**(精确 token如 ID、环境变量、代码符号)
- **BM25 关键词相关性**(精确令牌如 ID、环境变量、代码符号)
如果你的平台上全文搜索不可用,OpenClaw 会回退到纯向量搜索。
#### 为什么用混合搜索?
#### 为什么使用混合搜索?
向量搜索擅长"这表达的是同一个意思"
向量搜索擅长"这意味着同一件事"
- "Mac Studio gateway 主机" vs "运行 gateway 的机器"
- "防抖文件更新" vs "避免每次写入都索引"
- "Mac Studio gateway host" vs "运行 gateway 的机器"
- "debounce file updates" vs "避免每次写入都索引"
对于精确的高信号 token 可能较弱:
它在精确的高信号令牌上可能较弱:
- ID`a828e60``b3b9895a…`
- 代码符号(`memorySearch.query.hybrid`
- 错误字符串("sqlite-vec unavailable"
BM25(全文搜索)恰好相反:擅长精确 token,较弱于同义改写。混合搜索是务实的折中方案:**同时使用两种检索信号**,这样"自然语言"查询和"大海捞针"查询都能获得好结果
BM25(全文)正好相反:擅长精确令牌,弱于释义
混合搜索是务实的中间地带:**同时使用两种检索信号**,这样你可以在"自然语言"查询和"大海捞针"查询上都获得好结果。
#### 我们如何合并结果(当前设计)
实现概
实现概
1.两端检索候选池:
1.双方检索候选池:
- **向量**:按余弦相似度取前 `maxResults * candidateMultiplier` 个。
- **BM25**:按 FTS5 BM25 排名取前 `maxResults * candidateMultiplier` 个(越低越好)。
- **BM25**:按 FTS5 BM25 排名取前 `maxResults * candidateMultiplier` 个(越低越好)。
2. 将 BM25 排名转换为 0..1 范围的分数:
- `textScore = 1 / (1 + max(0, bm25Rank))`
3.ID 合并候选并计算加权分数:
3. 按块 id 合并候选并计算加权分数:
- `finalScore = vectorWeight * vectorScore + textWeight * textScore`
注意事项
说明
- 在配置解析 `vectorWeight` + `textWeight` 归一化 1.0,因此权重表现为百分比。
- 如果嵌入不可用(或提供商返回零向量),我们仍运行 BM25 并返回关键词匹配结果
- 在配置解析 `vectorWeight` + `textWeight` 归一化 1.0,因此权重表现为百分比。
- 如果嵌入不可用(或提供商返回零向量),我们仍运行 BM25 并返回关键词匹配。
- 如果无法创建 FTS5,我们保持纯向量搜索(不会硬失败)。
这不是"信息检索理论上的完美方案",但它简单、快速,在实际笔记上倾向于提升召回率/精确率。如果以后想更精细,常见的下一步是互惠排名融合(RRF)或混合前的分数归一化(最小/最大值或 z-score)
这不是"IR 理论完美"的,但它简单、快速,并且往往能提高真实笔记的召回率/精确率
如果我们以后想要更复杂的方案,常见的下一步是倒数排名融合(RRF)或在混合之前进行分数归一化(最小/最大或 z 分数)。
配置:
@@ -290,7 +292,7 @@ agents: {
### 嵌入缓存
OpenClaw 可以在 SQLite 中缓存**块嵌入**,这样重新索引和频繁更新(特别是会话记录)不会重新嵌入未更改的文本。
OpenClaw 可以在 SQLite 中缓存**块嵌入**,这样重新索引和频繁更新(特别是会话记录)不会重新嵌入未更改的文本。
配置:
@@ -309,7 +311,8 @@ agents: {
### 会话记忆搜索(实验性)
你可以选择索引**会话记录**并通过 `memory_search` 进行搜索。此功能受实验性标志控制
你可以选择性地索引**会话记录**并通过 `memory_search` 呈现它们
这由实验性标志控制。
```json5
agents: {
@@ -322,14 +325,14 @@ agents: {
}
```
注意事项
说明
- 会话索引是**选择加入**的(默认关闭)。
- 会话更新带防抖,在超过增量阈值后**异步索引**(尽力而为)。
- `memory_search` 不会阻塞等待索引;在后台同步完成之前结果可能略有延迟。
- 结果仍然只包含片段;`memory_get` 仍限于记忆文件。
- 会话更新被去抖动并在超过增量阈值后**异步索引**(尽力而为)。
- `memory_search` 永远不会阻塞索引;在后台同步完成之前结果可能略有延迟。
- 结果仍然只包含片段;`memory_get`然仅限于记忆文件。
- 会话索引按智能体隔离(仅索引该智能体的会话日志)。
- 会话日志存储在磁盘上(`~/.openclaw/agents/<agentId>/sessions/*.jsonl`)。任何有文件系统访问权限的进程/用户都可以读取它们,因此将磁盘访问视为信任边界。如需更严格的隔离,请在不同的操作系统用户或主机下运行智能体。
- 会话日志存储在磁盘上(`~/.openclaw/agents/<agentId>/sessions/*.jsonl`)。任何有文件系统访问权限的进程/用户都可以读取它们,因此将磁盘访问视为信任边界。对于更严格的隔离,在单独的操作系统用户或主机下运行智能体。
增量阈值(显示默认值):
@@ -350,7 +353,7 @@ agents: {
### SQLite 向量加速(sqlite-vec
当 sqlite-vec 扩展可用时,OpenClaw 将嵌入存储在 SQLite 虚拟表(`vec0`)中,并在数据库执行向量距离查询。这使搜索保持快速,无需将所有嵌入加载到 JS 中。
当 sqlite-vec 扩展可用时,OpenClaw 将嵌入存储在 SQLite 虚拟表(`vec0`)中,并在数据库执行向量距离查询。这使搜索保持快速,无需将每个嵌入加载到 JS 中。
配置(可选):
@@ -369,18 +372,18 @@ agents: {
}
```
注意事项
说明
- `enabled` 默认为 true;禁用时,搜索回退到对存储嵌入进行进程内余弦相似度计算。
- `enabled` 默认为 true;禁用时,搜索回退到对存储嵌入进程内余弦相似度计算。
- 如果 sqlite-vec 扩展缺失或加载失败,OpenClaw 会记录错误并继续使用 JS 回退(无向量表)。
- `extensionPath` 覆盖捆绑的 sqlite-vec 路径(适用于自定义构建或非标准安装位置)。
- `extensionPath` 覆盖捆绑的 sqlite-vec 路径(于自定义构建或非标准安装位置很有用)。
### 本地嵌入自动下载
- 默认本地嵌入模型:`hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf`(约 0.6 GB)。
-`memorySearch.provider = "local"` 时,`node-llama-cpp` 解析 `modelPath`;如果 GGUF 文件缺失,会**自动下载**到缓存目录(或 `local.modelCacheDir`,如已设置),然后加载。下载在重试时可恢复
-`memorySearch.provider = "local"` 时,`node-llama-cpp` 解析 `modelPath`;如果 GGUF 缺失,会**自动下载**到缓存(或 `local.modelCacheDir`,如已设置),然后加载。下载在重试时会续传
- 原生构建要求:运行 `pnpm approve-builds`,选择 `node-llama-cpp`,然后运行 `pnpm rebuild node-llama-cpp`
- 回退:如果本地设置失败且 `memorySearch.fallback = "openai"`,我们自动切换到远程嵌入(`openai/text-embedding-3-small`,除非被覆盖)并记录原因。
- 回退:如果本地设置失败且 `memorySearch.fallback = "openai"`,我们自动切换到远程嵌入(`openai/text-embedding-3-small`,除非被覆盖)并记录原因。
### 自定义 OpenAI 兼容端点示例
@@ -403,7 +406,7 @@ agents: {
}
```
注意事项
说明
- `remote.*` 优先于 `models.providers.openai.*`
- `remote.headers` 与 OpenAI 请求头合并;键冲突时 remote 优先。省略 `remote.headers` 使用 OpenAI 默认值。
- `remote.headers` 与 OpenAI 头合并;键冲突时 remote 优先。省略 `remote.headers` 使用 OpenAI 默认值。
+51 -51
View File
@@ -1,50 +1,50 @@
---
read_when:
- 解释入站消息如何为回复
- 澄清会话、队列模式或流式传输行为
- 记录推理可见性和用影响
summary: 消息流、会话、队列和推理可见性
- 解释入站消息如何转化为回复
- 阐明会话、队列模式或流式传输行为
- 记录推理可见性和使用影响
summary: 消息流、会话、队列和推理可见性
title: 消息
x-i18n:
generated_at: "2026-02-01T20:22:57Z"
generated_at: "2026-02-03T10:05:22Z"
model: claude-opus-4-5
provider: pi
source_hash: 147362b61bee21ee6e303654d970a052325f076ddb45814306053f70409737b5
source_path: concepts/messages.md
workflow: 14
workflow: 15
---
# 消息
本页汇总了 OpenClaw 处理入站消息、会话、队列、流式传输和推理可见性的方式
本页汇总了 OpenClaw 如何处理入站消息、会话、队列、流式传输和推理可见性。
## 消息流(概览
## 消息流程(高层概述
```
入站消息
-> 路由/绑定 -> 会话
-> 路由/绑定 -> 会话密钥
-> 队列(如果有运行中的任务)
-> 智能体运行(流式传输 + 工具)
-> 出站回复(渠道限制 + 分块)
```
关键配置项位于配置文件中:
关键配置项在配置中:
- `messages.*` 用于前缀、队列和群组行为。
- `agents.defaults.*` 用于块流式传输和分块默认值。
- `agents.defaults.*` 用于块流式传输和分块默认值。
- 渠道覆盖(`channels.whatsapp.*``channels.telegram.*` 等)用于上限和流式传输开关。
完整配置结构请参见[配置](/gateway/configuration)。
完整 schema 参见[配置](/gateway/configuration)。
## 入站去重
渠道在重新连接后可能会重新投递相同的消息。OpenClaw 维护一个短期缓存,以渠道/账/对端/会话/消息 ID 为键,避免重复投递触发额外的智能体运行。
渠道可能在重新连接后重复投递同一消息。OpenClaw 保持一个短期缓存,以渠道/账/对端/会话/消息 ID 为键,因此重复投递不会触发另一次智能体运行。
## 入站防抖
来自**同一发送者**的快速连续消息可以通过 `messages.inbound` 合并为单个智能体轮次。防抖按渠道 + 对话维度隔离,并使用最消息进行回复线程/ID 关联
来自**同一发送者**的快速连续消息可以通过 `messages.inbound` 批量合并为单个智能体轮次。防抖按渠道 + 会话为范围,并使用最近的消息进行回复线程/ID 处理
配置(全局默认 + 渠道覆盖):
配置(全局默认 + 渠道覆盖):
```json5
{
@@ -61,54 +61,54 @@ x-i18n:
}
```
说明
注意事项
- 防抖仅适用于**纯文本**消息;媒体/附件会立即发送
- 控制命令会绕过防抖,保持独立消息
- 防抖仅适用于**纯文本**消息;媒体/附件会立即刷新
- 控制命令会绕过防抖,保持独立。
## 会话设备
## 会话设备
会话由 Gateway网关管理,而非客户端管理
会话由 Gateway 网关拥有,而非客户端。
- 私聊消息归并到智能体主会话
- 群组/频道拥有各自独立的会话
- 会话存储和对话记录保存在 Gateway网关主机上。
- 直接聊天合并到智能体主会话密钥
- 群组/渠道获得各自的会话密钥
- 会话存储和记录保存在 Gateway 网关主机上。
多个设备/渠道可以映射到同一会话,但历史记录不会完全同步回每个客户端。建议:长对话使用一个主设备,以避免上下文分歧。控制界面和 TUI 始终显示 Gateway网关的会话记录,因此它们是权威数据源。
多个设备/渠道可以映射到同一会话,但历史记录不会完全同步回每个客户端。建议:长对话使用一个主设备,以避免上下文分歧。控制 UI 和 TUI 始终显示 Gateway 网关支持的会话记录,因此它们是事实来源。
详情请参见[会话管理](/concepts/session)。
详情:[会话管理](/concepts/session)。
## 入站消息体和历史上下文
## 入站正文和历史上下文
OpenClaw 将**提示词体**与**命令**分开处理
OpenClaw 将**提示正文**与**命令正文**分开:
- `Body`:发送给智能体的提示文本。可能包渠道信封和可选的历史包装。
- `Body`:发送给智能体的提示文本。可能包渠道信封和可选的历史包装
- `CommandBody`:用于指令/命令解析的原始用户文本。
- `RawBody``CommandBody` 的旧别名(保留以兼容)。
- `RawBody``CommandBody` 的旧别名(为兼容性保留)。
当渠道提供历史记录时,使用共享包装格式
当渠道提供历史记录时,使用共享包装
- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
对于**非私聊**(群组/道/房间),**当前消息**会加发送者标签前缀(与历史条目使用相同的格式)。这使得实时消息和队/历史消息在智能体提示词中保持一致。
对于**非直接聊天**(群组/道/房间),**当前消息正文**会加发送者标签前缀(与历史条目使用的样式相同)。这使智能体提示中的实时消息和队/历史消息保持一致。
历史缓冲区**仅待处理消息**:它们包含触发运行的群组消息(例如,提及门控的消息),并**排除**已在会话记录中的消息。
历史缓冲区**仅待处理**:它们包含*未*触发运行的群组消息(例如,提及门控的消息),并**排除**已在会话记录中的消息。
指令剥离仅适用于**当前消息**部分,历史记录保持不变。包装历史记录的渠道应将 `CommandBody`(或 `RawBody`)设置为原始消息文本,并将 `Body` 保留为组合提示。历史缓冲区可通过 `messages.groupChat.historyLimit`(全局默认)和渠道覆盖进行配置,例`channels.slack.historyLimit``channels.telegram.accounts.<id>.historyLimit`(设置 `0` 禁用)。
指令剥离仅适用于**当前消息**部分,因此历史记录保持完整。包装历史记录的渠道应将 `CommandBody`(或 `RawBody`)设置为原始消息文本,并将 `Body` 保留为组合提示。历史缓冲区可通过 `messages.groupChat.historyLimit`(全局默认)和渠道覆盖`channels.slack.historyLimit``channels.telegram.accounts.<id>.historyLimit`)进行配置(设置 `0` 表示禁用)。
## 队列后续消息
## 队列后续消息
如果已有运行中的任务,入站消息可以排队、引导至当前运行,或收集用于后续轮次。
如果运行已在进行中,入站消息可以排队、导入当前运行,或收集用于后续轮次。
- 通过 `messages.queue` `messages.queue.byChannel`进行配置。
- 模式:`interrupt``steer``followup``collect`,以及 backlog 变体。
- 通过 `messages.queue` `messages.queue.byChannel`)配置。
- 模式:`interrupt``steer``followup``collect`,以及积压变体。
详情请参见[队列](/concepts/queue)。
详情:[队列](/concepts/queue)。
## 流式传输、分块批处理
## 流式传输、分块批处理
块流式传输在模型生成文本块时发送部分回复。分块遵循渠道文本限制,避免拆分代码围栏。
块流式传输在模型生成文本块时发送部分回复。分块遵循渠道文本限制,避免拆分围栏代码
关键设置:
@@ -116,26 +116,26 @@ OpenClaw 将**提示词体**与**命令体**分开处理:
- `agents.defaults.blockStreamingBreak``text_end|message_end`
- `agents.defaults.blockStreamingChunk``minChars|maxChars|breakPreference`
- `agents.defaults.blockStreamingCoalesce`(基于空闲的批处理)
- `agents.defaults.humanDelay`(块回复之间的仿人类停顿
- `agents.defaults.humanDelay`(块回复之间的拟人化暂停
- 渠道覆盖:`*.blockStreaming``*.blockStreamingCoalesce`(非 Telegram 渠道需要显式设置 `*.blockStreaming: true`
详情请参见[流式传输 + 分块](/concepts/streaming)。
详情:[流式传输 + 分块](/concepts/streaming)。
## 推理可见性与令牌
## 推理可见性和 token
OpenClaw 可以显示或隐藏模型推理过程
OpenClaw 可以显示或隐藏模型推理:
- `/reasoning on|off|stream` 控制可见性。
- 推理内容在模型生成时仍然计入令牌用量。
- Telegram 支持将推理过程流式传输到草稿气泡中。
- 当模型产生推理内容时,它仍计入 token 使用量。
- Telegram 支持将推理流式传输到草稿气泡中。
详情请参见[思考 + 推理指令](/tools/thinking) 和 [令牌用量](/token-use)。
详情:[思考 + 推理指令](/tools/thinking)和 [Token 使用](/token-use)。
## 前缀、线程回复
## 前缀、线程回复
出站消息格式集中`messages`管理
出站消息格式在 `messages`集中配置
- `messages.responsePrefix`(出站前缀)和 `channels.whatsapp.messagePrefix`WhatsApp 入站前缀)
- 通过 `replyToMode`渠道默认值进行回复线程关联
- 通过 `replyToMode`渠道默认值进行回复线程
详情请参见[配置](/gateway/configuration#messages) 和各渠道文档。
详情:[配置](/gateway/configuration#messages)渠道文档。
+36 -47
View File
@@ -1,16 +1,16 @@
---
read_when:
- 诊断认证配置文件轮换、冷却或模型回退行为
- 诊断认证配置文件轮换、冷却时间或模型回退行为
- 更新认证配置文件或模型的故障转移规则
summary: OpenClaw 如何轮换认证配置文件并在模型之间进行故障回退
summary: OpenClaw 如何轮换认证配置文件并在模型之间进行回退
title: 模型故障转移
x-i18n:
generated_at: "2026-02-01T20:23:02Z"
generated_at: "2026-02-03T07:46:17Z"
model: claude-opus-4-5
provider: pi
source_hash: eab7c0633824d941cf0d6ce4294f0bc8747fbba2ce93650e9643eca327cd04a9
source_path: concepts/model-failover.md
workflow: 14
workflow: 15
---
# 模型故障转移
@@ -20,78 +20,70 @@ OpenClaw 分两个阶段处理故障:
1. 在当前提供商内进行**认证配置文件轮换**。
2. **模型回退**到 `agents.defaults.model.fallbacks` 中的下一个模型。
本文档介绍运行时规则及其背后的数据。
本文档解释运行时规则及其背后的数据。
## 认证存储(密钥 + OAuth
OpenClaw 对 API 密钥和 OAuth 令牌都使用**认证配置文件**。
- 密钥存储在 `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`(旧版路径`~/.openclaw/agent/auth-profiles.json`)。
- 配置 `auth.profiles` / `auth.order` **仅包含元数据和路由信息**(不含密钥)。
- 旧版仅导入 OAuth 文件:`~/.openclaw/credentials/oauth.json`(首次使用时导入到 `auth-profiles.json`)。
- 密钥存储在 `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`(旧版:`~/.openclaw/agent/auth-profiles.json`)。
- 配置 `auth.profiles` / `auth.order` **仅用于元数据和路由**(不含密钥)。
- 旧版仅导入 OAuth 文件:`~/.openclaw/credentials/oauth.json`(首次使用时导入到 `auth-profiles.json`)。
更多详情:[/concepts/oauth](/concepts/oauth)
凭证类型:
- `type: "api_key"``{ provider, key }`
- `type: "oauth"``{ provider, access, refresh, expires, email? }`部分提供商还包含 `projectId`/`enterpriseUrl`
- `type: "oauth"``{ provider, access, refresh, expires, email? }`某些提供商还 `projectId`/`enterpriseUrl`
## 配置文件 ID
OAuth 登录创建不同的配置文件,以便多个账户共存。
OAuth 登录创建不同的配置文件,以便多个账户可以共存。
- 默认:当没有可用邮箱时为 `provider:default`
-邮箱的 OAuth`provider:<email>`(例如 `google-antigravity:user@gmail.com`)。
- 默认:当没有电子邮件可用时为 `provider:default`
-电子邮件的 OAuth`provider:<email>`(例如 `google-antigravity:user@gmail.com`)。
配置文件存储在 `~/.openclaw/agents/<agentId>/agent/auth-profiles.json``profiles` 下。
## 轮换顺序
当一个提供商有多个配置文件时,OpenClaw 按如下方式选择顺序
当一个提供商有多个配置文件时,OpenClaw 按以下顺序选择
1. **显式配置**`auth.order[provider]`(如果设置)。
1. **显式配置**`auth.order[provider]`(如果设置)。
2. **已配置的配置文件**:按提供商过滤的 `auth.profiles`
3. **已存储的配置文件**`auth-profiles.json` 中该提供商的条目。
如果配置显式顺序,OpenClaw 使用轮询顺序:
如果没有配置显式顺序,OpenClaw 使用轮询顺序:
- **主排序键:** 配置文件类型(**OAuth 优先于 API 密钥**)。
- **次排序键:** `usageStats.lastUsed`类型最旧的优先)。
- **冷却中/已禁用的配置文件**移到末尾,按最早期时间排序。
- **主键:** 配置文件类型(**OAuth 优先于 API 密钥**)。
- **次键:** `usageStats.lastUsed`每种类型最旧的优先)。
- **冷却/禁用的配置文件**移到末尾,按最早期时间排序。
### 会话粘性(缓存友好)
OpenClaw **每个会话固定选的认证配置文件**以保持提供商缓存活跃。
它**不会**在每次请求时轮换。固定的配置文件会持续使用,直到:
OpenClaw **每个会话固定选的认证配置文件**以保持提供商缓存热度。它**不会**在每个请求时轮换。固定的配置文件会被重用直到:
- 会话被重置(`/new` / `/reset`
- 压缩完成(压缩计数递增)
- 配置文件处于冷却中/已禁用状态
- 配置文件处于冷却/禁用状态
通过 `/model …@<profileId>` 手动选择会为该会话设置一个**用户覆盖**
在新会话开始前不会自动轮换。
通过 `/model …@<profileId>` 手动选择会为该会话设置**用户覆盖**,在新会话开始之前不会自动轮换。
自动固定的配置文件(由会话路由器选择)被视为一种**偏好**
它们会优先尝试,但 OpenClaw 可能在遇到速率限制/超时时轮换到其他配置文件。
用户固定的配置文件会锁定在该配置文件上;如果它失败且配置了模型回退,
OpenClaw 会转移到下一个模型,而不是切换配置文件。
自动固定的配置文件(由会话路由器选择)被视为**偏好**:它们会优先尝试,但 OpenClaw 可能在速率限制/超时时轮换到另一个配置文件。用户固定的配置文件会锁定到该配置文件;如果失败且配置了模型回退,OpenClaw 会移动到下一个模型而不是切换配置文件。
### 为什么 OAuth 可能"看起来丢失"
### 为什么 OAuth 可能"看起来丢失"
如果你同一个提供商同时拥有 OAuth 配置文件和 API 密钥配置文件,轮询可能在消息之间切换它们(除非已固定)。要强制使用单个配置文件:
如果你同一个提供商同时拥有 OAuth 配置文件和 API 密钥配置文件,除非固定,否则轮询可能在消息之间切换它们。要强制使用单个配置文件:
- 通过 `auth.order[provider] = ["provider:profileId"]` 固定,或
- 通过 `/model …` 使用会话覆盖并指定配置文件(当你的 UI/聊天界面支持时)。
- 使用 `auth.order[provider] = ["provider:profileId"]` 固定,或
- 通过 `/model …` 使用会话覆盖并指定配置文件覆盖(当你的 UI/聊天界面支持时)。
## 冷却
## 冷却时间
当配置文件因认证/速率限制错误(或看起来像速率限制的超时)而失败时,
OpenClaw 会将其标记为冷却状态并移至下一个配置文件。
格式/无效请求错误(例如 Cloud Code Assist 工具调用 ID
验证失败)也被视为可故障转移的,并使用相同的冷却机制。
当配置文件因认证/速率限制错误(或看起来像速率限制的超时)而失败时,OpenClaw 将其标记为冷却状态并移动到下一个配置文件。格式/无效请求错误(例如 Cloud Code Assist 工具调用 ID 验证失败)被视为值得故障转移的情况,使用相同的冷却时间。
冷却使用指数退避:
冷却时间使用指数退避:
- 1 分钟
- 5 分钟
@@ -112,9 +104,9 @@ OpenClaw 会将其标记为冷却状态并移至下一个配置文件。
}
```
## 计费禁用
## 账单禁用
计费/额度失败(例如"额度不足"/"信用余额过低")被视为故障转移的,但通常不是时性的。OpenClaw 不使用短冷却,而是将配置文件标记为**禁用**(使用更长的退避时间)并轮换到下一个配置文件/提供商。
账单/额度失败(例如"insufficient credits"/"credit balance too low")被视为值得故障转移的情况,但它们通常不是时性的。OpenClaw 不使用短冷却时间,而是将配置文件标记为**禁用**(使用更长的退避时间)并轮换到下一个配置文件/提供商。
状态存储在 `auth-profiles.json` 中:
@@ -131,21 +123,18 @@ OpenClaw 会将其标记为冷却状态并移至下一个配置文件。
默认值:
- 计费退避从 **5 小时**开始,每次计费失败倍,上限为 **24 小时**
- 如果配置文件 **24 小时**内失败,退避计数器重置(可配置)。
- 账单退避从 **5 小时**开始,每次账单失败倍,上限为 **24 小时**
- 如果配置文件 **24 小时**内没有失败,退避计数器重置(可配置)。
## 模型回退
如果某个提供商的所有配置文件都失败,OpenClaw 会移
`agents.defaults.model.fallbacks` 中的下一个模型。这适用于认证失败、速率限制和
耗尽配置文件轮换的超时情况(其他错误不会触发回退)。
如果某个提供商的所有配置文件都失败,OpenClaw 会移动到 `agents.defaults.model.fallbacks` 中的下一个模型。这适用于认证失败、速率限制和耗尽配置文件轮换的超时(其他错误不会推进回退)。
当运行以模型覆盖(钩子或 CLI启动时,回退仍会在尝试所有已配置的回退后
止于 `agents.defaults.model.primary`
当运行以模型覆盖(钩子或 CLI开始时,在尝试任何配置的回退之后,回退仍会在 `agents.defaults.model.primary` 处结束。
## 相关配置
参阅 [Gateway网关配置](/gateway/configuration) 了解:
参阅 [Gateway 网关配置](/gateway/configuration) 了解:
- `auth.profiles` / `auth.order`
- `auth.cooldowns.billingBackoffHours` / `auth.cooldowns.billingBackoffHoursByProvider`
+32 -29
View File
@@ -1,32 +1,32 @@
---
read_when:
- 你需要按提供商查阅模型设置参考
- 你需要按提供商分类的模型设置参考
- 你需要模型提供商的示例配置或 CLI 新手引导命令
summary: 模型提供商概,包含示例配置和 CLI 流程
summary: 模型提供商概,包含示例配置和 CLI 流程
title: 模型提供商
x-i18n:
generated_at: "2026-02-01T20:23:13Z"
generated_at: "2026-02-03T07:46:28Z"
model: claude-opus-4-5
provider: pi
source_hash: b3940c91ce3aee3d701af7978284966a60ec8c669649cc4be48ba9472243e444
source_hash: 14f73e5a9f9b7c6f017d59a54633942dba95a3eb50f8848b836cfe0b9f6d7719
source_path: concepts/model-providers.md
workflow: 14
workflow: 15
---
# 模型提供商
本页介绍 **LLM/模型提供商** WhatsApp/Telegram 等聊天渠道)。
关模型选择规则,请参 [/concepts/models](/concepts/models)。
本页介绍 **LLM/模型提供商**不是 WhatsApp/Telegram 等聊天渠道)。
模型选择规则,请参 [/concepts/models](/concepts/models)。
## 快速规则
- 模型引用使用 `provider/model` 格式(例如:`opencode/claude-opus-4-5`)。
- 如果设置了 `agents.defaults.models`,它将成为白名单
- CLI 辅助命令`openclaw onboard``openclaw models list``openclaw models set <provider/model>`
- 如果设置了 `agents.defaults.models`,它将成为允许列表
- CLI 辅助工具`openclaw onboard``openclaw models list``openclaw models set <provider/model>`
## 内置提供商(pi-ai 目录)
OpenClaw 带 piai 目录。这些提供商**无需**配置 `models.providers`;只需设置认证选择模型即可
OpenClaw 带 pi-ai 目录。这些提供商**不需要** `models.providers` 配置;只需设置认证 + 选择模型。
### OpenAI
@@ -97,7 +97,7 @@ OpenClaw 自带 piai 目录。这些提供商**无需**配置 `models.provide
- Gemini CLI OAuth 作为捆绑插件提供(`google-gemini-cli-auth`,默认禁用)。
- 启用:`openclaw plugins enable google-gemini-cli-auth`
- 登录:`openclaw models auth login --provider google-gemini-cli --set-default`
- 注意:你**无需**将客户端 ID 或密钥粘贴到 `openclaw.json` 中。CLI 登录流程将令牌存储在 Gateway网关主机的认证配置文件中。
- 注意:你**不需要**将客户端 ID 或密钥粘贴到 `openclaw.json` 中。CLI 登录流程将令牌存储在 Gateway 网关主机的认证配置文件中。
### Z.AI (GLM)
@@ -105,7 +105,7 @@ OpenClaw 自带 piai 目录。这些提供商**无需**配置 `models.provide
- 认证:`ZAI_API_KEY`
- 示例模型:`zai/glm-4.7`
- CLI`openclaw onboard --auth-choice zai-api-key`
- 别名:`z.ai/*``z-ai/*` 规范化为 `zai/*`
- 别名:`z.ai/*``z-ai/*` 规范化为 `zai/*`
### Vercel AI Gateway
@@ -137,14 +137,17 @@ Moonshot 使用 OpenAI 兼容端点,因此将其配置为自定义提供商:
- 提供商:`moonshot`
- 认证:`MOONSHOT_API_KEY`
- 示例模型:`moonshot/kimi-k2.5`
- Kimi K2 模型 ID
{/_ moonshot-kimi-k2-model-refs:start _/}
- `moonshot/kimi-k2.5`
- `moonshot/kimi-k2-0905-preview`
- `moonshot/kimi-k2-turbo-preview`
- `moonshot/kimi-k2-thinking`
- `moonshot/kimi-k2-thinking-turbo`
{/_ moonshot-kimi-k2-model-refs:end _/}
Kimi K2 模型 ID
{/_ moonshot-kimi-k2-model-refs:start _/ && null}
- `moonshot/kimi-k2.5`
- `moonshot/kimi-k2-0905-preview`
- `moonshot/kimi-k2-turbo-preview`
- `moonshot/kimi-k2-thinking`
- `moonshot/kimi-k2-thinking-turbo`
{/_ moonshot-kimi-k2-model-refs:end _/ && null}
```json5
{
@@ -182,7 +185,7 @@ Kimi Coding 使用 Moonshot AI 的 Anthropic 兼容端点:
}
```
### Qwen OAuth(免费
### Qwen OAuth(免费层级
Qwen 通过设备码流程提供对 Qwen Coder + Vision 的 OAuth 访问。
启用捆绑插件,然后登录:
@@ -197,11 +200,11 @@ openclaw models auth login --provider qwen-portal --set-default
- `qwen-portal/coder-model`
- `qwen-portal/vision-model`
见 [/providers/qwen](/providers/qwen) 了解设置详情和注意事项。
见 [/providers/qwen](/providers/qwen) 了解设置详情和注意事项。
### Synthetic
Synthetic `synthetic` 提供商提供 Anthropic 兼容模型:
Synthetic 通过 `synthetic` 提供商提供 Anthropic 兼容模型:
- 提供商:`synthetic`
- 认证:`SYNTHETIC_API_KEY`
@@ -234,11 +237,11 @@ MiniMax 通过 `models.providers` 配置,因为它使用自定义端点:
- MiniMaxAnthropic 兼容):`--auth-choice minimax-api`
- 认证:`MINIMAX_API_KEY`
见 [/providers/minimax](/providers/minimax) 了解设置详情、模型选项和配置片段。
见 [/providers/minimax](/providers/minimax) 了解设置详情、模型选项和配置片段。
### Ollama
Ollama 是一个本地 LLM 运行时,提供 OpenAI 兼容 API
Ollama 是提供 OpenAI 兼容 API 的本地 LLM 运行时
- 提供商:`ollama`
- 认证:无需(本地服务器)
@@ -246,7 +249,7 @@ Ollama 是一个本地 LLM 运行时,提供 OpenAI 兼容的 API:
- 安装:https://ollama.ai
```bash
# 安装 Ollama,然后拉取模型:
# Install Ollama, then pull a model:
ollama pull llama3.3
```
@@ -258,7 +261,7 @@ ollama pull llama3.3
}
```
Ollama 在本地运行于 `http://127.0.0.1:11434/v1` 时会自动检测。见 [/providers/ollama](/providers/ollama) 了解模型推荐和自定义配置。
Ollama 在本地 `http://127.0.0.1:11434/v1` 运行时会自动检测。见 [/providers/ollama](/providers/ollama) 了解模型推荐和自定义配置。
### 本地代理(LM Studio、vLLM、LiteLLM 等)
@@ -304,7 +307,7 @@ Ollama 在本地运行于 `http://127.0.0.1:11434/v1` 时会被自动检测。
- `cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }`
- `contextWindow: 200000`
- `maxTokens: 8192`
- 建议:设置与你的代理/模型限制匹配的明确值。
- 建议:设置与你的代理/模型限制匹配的显式值。
## CLI 示例
@@ -314,4 +317,4 @@ openclaw models set opencode/claude-opus-4-5
openclaw models list
```
另请参[/gateway/configuration](/gateway/configuration) 了解全部配置示例。
另请参[/gateway/configuration](/gateway/configuration) 了解完整配置示例。
+41 -41
View File
@@ -1,76 +1,76 @@
---
read_when:
- 添加或修改模型 CLImodels list/set/scan/aliases/fallbacks
- 更改模型回退行为或选择体验
- 更改模型回退行为或选择用户体验
- 更新模型扫描探测(工具/图像)
summary: 模型 CLI:列表、设置、别名、回退、扫描、状态
title: 模型 CLI
x-i18n:
generated_at: "2026-02-01T20:23:26Z"
generated_at: "2026-02-03T10:05:42Z"
model: claude-opus-4-5
provider: pi
source_hash: e8b54bb370b4f63a9b917594fb0f6ff48192e168196d30c713b8bbe72b78fef6
source_path: concepts/models.md
workflow: 14
workflow: 15
---
# 模型 CLI
认证配置轮换、冷却时间以及与回退的交互方式请参见 [/concepts/model-failover](/concepts/model-failover)。
提供商快速概览 + 示例:[/concepts/model-providers](/concepts/model-providers)。
参见 [/concepts/model-failover](/concepts/model-failover) 了解认证配置文件轮换、冷却时间及其与回退的交互
快速提供商概述 + 示例:[/concepts/model-providers](/concepts/model-providers)。
## 模型选择工作方式
## 模型选择工作原理
OpenClaw 按以下顺序选择模型:
1. **主模型**`agents.defaults.model.primary``agents.defaults.model`)。
2. `agents.defaults.model.fallbacks` 中的**回退模型**(按顺序)。
3. **提供商认证故障转移**在切换到下一个模型之前,会先在提供商内部进行
1. **主要**模型(`agents.defaults.model.primary``agents.defaults.model`)。
2. `agents.defaults.model.fallbacks` 中的**回退**(按顺序)。
3. **提供商认证故障转移**在移动到下一个模型之前在提供商内部发生
相关说明
相关:
- `agents.defaults.models` 是 OpenClaw 可使用的模型白名单/目录(别名)。
- `agents.defaults.imageModel` **仅在**主模型无法处理图像时使用。
- `agents.defaults.models` 是 OpenClaw 可使用的模型白名单/目录(加上别名)。
- `agents.defaults.imageModel` **仅在**主模型无法接受图像时使用。
- 每个智能体的默认值可以通过 `agents.list[].model` 加绑定覆盖 `agents.defaults.model`(参见 [/concepts/multi-agent](/concepts/multi-agent))。
## 快速模型推荐(经验之谈)
- **GLM**:在编/工具调用方面稍好。
- **MiniMax**:在写作和风格表现方面更好。
- **GLM**:在编/工具调用方面稍好。
- **MiniMax**:在写作和氛围方面更好。
## 设置向导(推荐)
如果不想手动编辑配置,可以运行新手引导向导:
如果不想手动编辑配置,运行新手引导向导:
```bash
openclaw onboard
```
它可以为常见提供商设置模型认证,包括 **OpenAI Code (Codex) 订阅**OAuth)和 **Anthropic**(推荐使用 API 密钥;也支持 `claude setup-token`)。
它可以为常见提供商设置模型 + 认证,包括 **OpenAI CodeCodex订阅**OAuth)和 **Anthropic**(推荐使用 API 密钥;也支持 `claude setup-token`)。
## 配置键(概
## 配置键(概
- `agents.defaults.model.primary``agents.defaults.model.fallbacks`
- `agents.defaults.imageModel.primary``agents.defaults.imageModel.fallbacks`
- `agents.defaults.models`(白名单 + 别名 + 提供商参数)
- `models.providers`(写入 `models.json` 的自定义提供商)
模型引用会被统一转为小写。提供商别名如 `z.ai/*`规范化为 `zai/*`
模型引用会规范化为小写。提供商别名如 `z.ai/*` 会规范化为 `zai/*`
提供商配置示例(包括 OpenCode Zen请参见 [/gateway/configuration](/gateway/configuration#opencode-zen-multi-model-proxy)。
提供商配置示例(包括 OpenCode Zen [/gateway/configuration](/gateway/configuration#opencode-zen-multi-model-proxy)。
## "Model is not allowed"(以及为什么回复停止)
如果设置了 `agents.defaults.models`,它将成为 `/model` 和会话覆盖的**白名单**。当用户选择不在白名单中的模型时,OpenClaw 返回:
如果设置了 `agents.defaults.models`,它将成为 `/model` 和会话覆盖的**白名单**。当用户选择不在白名单中的模型时,OpenClaw 返回:
```
Model "provider/model" is not allowed. Use /model to list available models.
```
这发生在正常回复生成**之前**因此消息看起来可能像是"没有响应"。修复方法是:
这发生在正常回复生成**之前**所以消息可能感觉像"没有响应"。修复方法是:
-模型添加到 `agents.defaults.models`,或
- 清除白名单(`agents.defaults.models`),或
- 将模型添加到 `agents.defaults.models`,或
- 清除白名单(`agents.defaults.models`),或
-`/model list` 中选择一个模型。
白名单配置示例:
@@ -89,7 +89,7 @@ Model "provider/model" is not allowed. Use /model to list available models.
## 在聊天中切换模型(`/model`
你可以在当前会话中切换模型而无需重启
你可以在不重启的情况下切换当前会话的模型
```
/model
@@ -99,14 +99,14 @@ Model "provider/model" is not allowed. Use /model to list available models.
/model status
```
说明
注意事项
- `/model`(和 `/model list`)是一个紧凑的编号选择器(模型系列 + 可用提供商)。
- `/model`(和 `/model list`)是紧凑的编号选择器(模型系列 + 可用提供商)。
- `/model <#>` 从该选择器中选择。
- `/model status` 是详细视图(认证候选项,以及配置的提供商端点 `baseUrl` + `api` 模式)。
- 模型引用通过**第一个** `/` 进行分割解析。输入 `/model <ref>`使用 `provider/model` 格式
- 如果模型 ID 本身包含 `/`OpenRouter 风格),必须包含提供商前缀(例如:`/model openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商,OpenClaw 将输入视为别名或**默认提供商**的模型(仅在模型 ID 中不含 `/` 时有效)。
- `/model status` 是详细视图(认证候选项,以及配置的提供商端点 `baseUrl` + `api` 模式)。
- 模型引用通过**第一个** `/` 分割解析。输入 `/model <ref>` 时使用 `provider/model`
- 如果模型 ID 本身包含 `/`OpenRouter 风格),必须包含提供商前缀(例如:`/model openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商,OpenClaw 将输入视为别名或**默认提供商**的模型(仅在模型 ID 中没有 `/` 时有效)。
完整命令行为/配置:[斜杠命令](/tools/slash-commands)。
@@ -137,7 +137,7 @@ openclaw models image-fallbacks clear
### `models list`
默认显示已配置的模型。常用标志:
默认显示已配置的模型。有用的标志:
- `--all`:完整目录
- `--local`:仅本地提供商
@@ -147,12 +147,12 @@ openclaw models image-fallbacks clear
### `models status`
显示已解析的主模型、回退模型、图像模型,以及已配置提供商的认证概览。还会显示认证存储中找到的 OAuth 配置过期状态(默认在 24 小时内发出警告)。`--plain` 仅打印已解析的主模型。
显示已解析的主模型、回退、图像模型,以及已配置提供商的认证概述。它还显示认证存储中找到的配置文件的 OAuth 过期状态(默认在 24 小时内警告)。`--plain` 仅打印已解析的主模型。
OAuth 状态始终显示(并包含在 `--json` 输出中)。如果已配置的提供商没有凭证,`models status` 会打印 **Missing auth** 部分。
JSON 包 `auth.oauth`(警告窗口 + 配置文件)和 `auth.providers`(每个提供商的有效认证)。
使用 `--check` 进行自动化检测(缺失/过期时退出码为 `1`,即将过期时 `2`)。
JSON 包 `auth.oauth`(警告窗口 + 配置文件)和 `auth.providers`(每个提供商的有效认证)。
使用 `--check` 进行自动化(缺失/过期时退出 `1`,即将过期时退出 `2`)。
推荐的 Anthropic 认证方式是 Claude Code CLI setup-token在任何地方运行;如需要可粘贴到 Gateway网关主机上):
首选的 Anthropic 认证是 Claude Code CLI setup-token(在任何地方运行;如需要 Gateway 网关主机上粘贴):
```bash
claude setup-token
@@ -161,9 +161,9 @@ openclaw models status
## 扫描(OpenRouter 免费模型)
`openclaw models scan` 检查 OpenRouter 的**免费模型目录**,并可选择性地探测模型的工具和图像支持情况
`openclaw models scan` 检查 OpenRouter 的**免费模型目录**,并可选择性地探测模型的工具和图像支持。
主要标志:
关键标志:
- `--no-probe`:跳过实时探测(仅元数据)
- `--min-params <b>`:最小参数量(十亿)
@@ -173,7 +173,7 @@ openclaw models status
- `--set-default`:将 `agents.defaults.model.primary` 设置为第一个选择
- `--set-image`:将 `agents.defaults.imageModel.primary` 设置为第一个图像选择
探测需要 OpenRouter API 密钥(来自认证配置或 `OPENROUTER_API_KEY`)。没有密钥时,使用 `--no-probe` 仅列出候选模型
探测需要 OpenRouter API 密钥(来自认证配置文件`OPENROUTER_API_KEY`)。没有密钥时,使用 `--no-probe` 仅列出候选
扫描结果按以下顺序排名:
@@ -185,12 +185,12 @@ openclaw models status
输入
- OpenRouter `/models` 列表(筛选 `:free`
- 需要来自认证配置或 `OPENROUTER_API_KEY` 的 OpenRouter API 密钥(参见 [/environment](/environment)
- 需要来自认证配置文件`OPENROUTER_API_KEY` 的 OpenRouter API 密钥(参见 [/environment](/environment)
- 可选筛选器:`--max-age-days``--min-params``--provider``--max-candidates`
- 探测控制:`--timeout``--concurrency`
在 TTY 中运行时,你可以交互式选择回退模型。在非交互模式下,传 `--yes` 接受默认值。
在 TTY 中运行时,你可以交互式选择回退。在非交互模式下,传 `--yes` 接受默认值。
## 模型注册表(`models.json`
`models.providers` 中的自定义提供商会写入智能体目录下的 `models.json`(默认 `~/.openclaw/agents/<agentId>/models.json`)。除非 `models.mode` 设置为 `replace`,否则此文件默认会被合并。
`models.providers` 中的自定义提供商会写入智能体目录下的 `models.json`(默认 `~/.openclaw/agents/<agentId>/models.json`)。除非 `models.mode` 设置为 `replace`,否则此文件默认会被合并。
+69 -66
View File
@@ -1,46 +1,46 @@
---
read_when: 你希望在一个 Gateway网关进程中运行多个隔离的智能体(工作区 + 认证)。
read_when: You want multiple isolated agents (workspaces + auth) in one gateway process.
status: active
summary: 多智能体路由:隔离的智能体、渠道账户和绑定
title: 多智能体路由
x-i18n:
generated_at: "2026-02-01T20:23:55Z"
generated_at: "2026-02-03T07:47:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 1848266c632cd6c96ff99ea9eb9c17bbfe6d35fa1f90450853083e7c548d5324
source_path: concepts/multi-agent.md
workflow: 14
workflow: 15
---
# 多智能体路由
目标:在一个运行中的 Gateway网关中托管多个*隔离的*智能体(独立的工作区 + `agentDir` + 会话),以及多个渠道账户(例如两个 WhatsApp)。入站消息通过绑定路由到对应的智能体。
目标:多个*隔离的*智能体(独立的工作区 + `agentDir` + 会话),加上多个渠道账户(例如两个 WhatsApp)在一个运行的 Gateway 网关中。入站消息通过绑定路由到智能体。
## 什么是"一个智能体"
一个**智能体**是一个完全独立作用域的大脑,拥有自己的:
- **工作区**(文件、AGENTS.md/SOUL.md/USER.md、本地笔记、人设规则)。
- **状态目录**`agentDir`用于存储认证配置文件、模型注册表和智能体配置。
- **会话存储**(聊天历史 + 路由状态)位于 `~/.openclaw/agents/<agentId>/sessions`
- **状态目录**`agentDir`)用于认证配置文件、模型注册表和智能体配置。
- **会话存储**(聊天历史 + 路由状态)位于 `~/.openclaw/agents/<agentId>/sessions`
认证配置文件是**智能体隔离的**。每个智能体从自己的目录读取:
认证配置文件是**智能体独立的**。每个智能体从自己的位置读取:
```
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
```
主智能体凭证**不会**自动共享。切勿在智能体之间`agentDir`(会导致认证/会话冲突)。如果你想共享凭证,请将 `auth-profiles.json` 复制到另一个智能体的 `agentDir`
主智能体凭证**不会**自动共享。切勿在智能体之间`agentDir`会导致认证/会话冲突)。如果你想共享凭证,请将 `auth-profiles.json` 复制到另一个智能体的 `agentDir`
Skills 通过每个工作区的 `skills/` 文件夹智能体隔离,共享 Skills 可从 `~/.openclaw/skills` 获取。参[Skills智能体 vs 共享](/tools/skills#per-agent-vs-shared-skills)。
Skills 通过每个工作区的 `skills/` 文件夹实现每智能体独立,共享 Skills 可从 `~/.openclaw/skills` 获取。参[Skills智能体 vs 共享](/tools/skills#per-agent-vs-shared-skills)。
Gateway网关可以托管**一个智能体**(默认)或**多个智能体**并行运行
Gateway 网关可以托管**一个智能体**(默认)或**多个智能体**并行。
**工作区说明** 每个智能体的工作区是**默认工作目录**,而非严格的沙箱。相对路径在工作区内解析,但绝对路径可以访问主机的其他位置,除非启用了沙箱。参阅[沙箱](/gateway/sandboxing)。
**工作区注意事项** 每个智能体的工作区是**默认 cwd**,而不是硬性沙箱。相对路径在工作区内解析,但绝对路径可以访问主机的其他位置,除非启用了沙箱隔离。参见 [沙箱隔离](/gateway/sandboxing)。
## 路径(速查
## 路径(快速映射
- 配置文件`~/.openclaw/openclaw.json`(或 `OPENCLAW_CONFIG_PATH`
- 配置:`~/.openclaw/openclaw.json`(或 `OPENCLAW_CONFIG_PATH`
- 状态目录:`~/.openclaw`(或 `OPENCLAW_STATE_DIR`
- 工作区:`~/.openclaw/workspace`(或 `~/.openclaw/workspace-<agentId>`
- 智能体目录:`~/.openclaw/agents/<agentId>/agent`(或 `agents.list[].agentDir`
@@ -48,11 +48,11 @@ Gateway网关可以托管**一个智能体**(默认)或**多个智能体**
### 单智能体模式(默认)
如果你不做任何配置OpenClaw 运行单个智能体:
如果你什么都不做,OpenClaw 运行单个智能体:
- `agentId` 默认为 **`main`**。
- 会话键格式`agent:main:<mainKey>`
- 工作区默认为 `~/.openclaw/workspace`(设置了 `OPENCLAW_PROFILE` 时为 `~/.openclaw/workspace-<profile>`)。
- 会话键为 `agent:main:<mainKey>`
- 工作区默认为 `~/.openclaw/workspace`或当设置了 `OPENCLAW_PROFILE` 时为 `~/.openclaw/workspace-<profile>`)。
- 状态默认为 `~/.openclaw/agents/main/agent`
## 智能体助手
@@ -65,27 +65,27 @@ openclaw agents add work
然后添加 `bindings`(或让向导完成)来路由入站消息。
验证方式
验证:
```bash
openclaw agents list --bindings
```
## 多智能体 = 多用户、多人设
## 多智能体 = 多个人、多种人格
使用**多个智能体**,每个 `agentId` 成为一个**完全隔离的人**
使用**多个智能体**,每个 `agentId` 成为一个**完全隔离的人**
- **不同的手机号/账户**渠道 `accountId`)。
- **不同的格**智能体工作区文件`AGENTS.md``SOUL.md`)。
- **独立的认证 + 会话**(除非显式启用,否则无串扰)。
- **不同的电话号码/账户**渠道 `accountId`)。
- **不同的格**智能体工作区文件如 `AGENTS.md``SOUL.md`)。
- **独立的认证 + 会话**(除非明确启用,否则无交叉通信)。
使得**多个用户**可以共享一 Gateway网关服务器,同时保持各自的 AI "大脑"和数据隔离。
**多个人**共享一 Gateway 网关服务器,同时保持他们的 AI"大脑"和数据隔离。
## 一个 WhatsApp 号码,多个用户(私聊分流
## 一个 WhatsApp 号码,多个人(私信分割
你可以将**不同的 WhatsApp 私**路由到不同的智能体,同时使用**一个 WhatsApp 账户**。通过发送者 E.164 格式号码(如 `+15551234567`配合 `peer.kind: "dm"` 进行匹配。回复仍然同一个 WhatsApp 号码发出(没有按智能体发送者身份)。
你可以将**不同的 WhatsApp 私**路由到不同的智能体,同时保持**一个 WhatsApp 账户**。使用 `peer.kind: "dm"` 匹配发送者 E.164(如 `+15551234567`)。回复仍然来自同一个 WhatsApp 号码(无每智能体发送者身份)。
重要细节:私聊会折叠到智能体的**主会话键**,因此真正的隔离需要**每人一个智能体**。
重要细节:直接聊天折叠到智能体的**主会话键**,因此真正的隔离需要**每人一个智能体**。
示例:
@@ -110,32 +110,32 @@ openclaw agents list --bindings
}
```
说明
注意事项
-访问控制是** WhatsApp 账户全局的**(配对/白名单),而非按智能体。
- 对于共享群组,将群组绑定到一个智能体或使用[广播群组](/broadcast-groups)。
-访问控制是** WhatsApp 账户全局的**(配对/允许列表),而不是每智能体。
- 对于共享群组,将群组绑定到一个智能体或使用 [广播群组](/broadcast-groups)。
## 路由规则(消息如何选择智能体)
绑定是**确定性的**遵循**最精确匹配优先**原则
绑定是**确定性的****最具体的优先**
1. `peer` 匹配(精确的私聊/群组/ID
1. `peer` 匹配(精确私信/群组/id
2. `guildId`Discord
3. `teamId`Slack
4. `accountId` 匹配(按渠道)
4. 渠道的 `accountId` 匹配
5. 渠道级匹配(`accountId: "*"`
6. 回退到默认智能体(`agents.list[].default`,否则列表第一项,默认`main`
6. 回退到默认智能体(`agents.list[].default`,否则列表中的第一个条目,默认:`main`
## 多账户/多手机号
## 多账户/电话号码
支持**多账户**的渠道(如 WhatsApp)使用 `accountId`识每个登录。每个 `accountId` 可以路由到不同的智能体,这样一台服务器可以托管多个手机号而不会混淆会话。
支持**多账户**的渠道(如 WhatsApp)使用 `accountId` 来识每个登录。每个 `accountId` 可以路由到不同的智能体,因此一个服务器可以托管多个电话号码而不混合会话。
## 概念
- `agentId`:一个"大脑"(工作区、智能体认证、智能体会话存储)。
- `agentId`:一个"大脑"(工作区、智能体认证、智能体会话存储)。
- `accountId`:一个渠道账户实例(例如 WhatsApp 账户 `"personal"` vs `"biz"`)。
- `binding`:通过 `(channel, accountId, peer)` 以及可选的 guild/team ID 将入站消息路由到 `agentId`
- 私聊折叠到 `agent:<agentId>:<mainKey>`智能体"主会话"`session.mainKey`)。
- `binding`:通过 `(channel, accountId, peer)` 以及可选的 guild/team id 将入站消息路由到 `agentId`
- 直接聊天折叠到 `agent:<agentId>:<mainKey>`智能体"主"`session.mainKey`)。
## 示例:两个 WhatsApp → 两个智能体
@@ -161,12 +161,12 @@ openclaw agents list --bindings
],
},
// 确定性路由:第一个匹配生效(最精确的在前)。
// 确定性路由:第一个匹配获胜(最具体的优先)。
bindings: [
{ agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
// 可选的按对端覆盖(示例:将特定群组发送到 work 智能体)。
// 可选的每对等方覆盖(示例:将特定群组发送到 work 智能体)。
{
agentId: "work",
match: {
@@ -177,7 +177,7 @@ openclaw agents list --bindings
},
],
// 默认关闭:智能体间消息传递必须显式启用 + 白名单
// 默认关闭:智能体到智能体的消息必须明确启用 + 加入允许列表
tools: {
agentToAgent: {
enabled: false,
@@ -189,11 +189,11 @@ openclaw agents list --bindings
whatsapp: {
accounts: {
personal: {
// 可选覆盖。默认~/.openclaw/credentials/whatsapp/personal
// 可选覆盖。默认:~/.openclaw/credentials/whatsapp/personal
// authDir: "~/.openclaw/credentials/whatsapp/personal",
},
biz: {
// 可选覆盖。默认~/.openclaw/credentials/whatsapp/biz
// 可选覆盖。默认:~/.openclaw/credentials/whatsapp/biz
// authDir: "~/.openclaw/credentials/whatsapp/biz",
},
},
@@ -204,7 +204,7 @@ openclaw agents list --bindings
## 示例:WhatsApp 日常聊天 + Telegram 深度工作
按渠道分:将 WhatsApp 路由到快速日常智能体,Telegram 路由到 Opus 智能体。
按渠道分:将 WhatsApp 路由到快速日常智能体,Telegram 路由到 Opus 智能体。
```json5
{
@@ -231,14 +231,14 @@ openclaw agents list --bindings
}
```
说明
注意事项
- 如果一个渠道多个账户,请在绑定中添加 `accountId`(例如 `{ channel: "whatsapp", accountId: "personal" }`)。
- 要将单个私/群组路由到 Opus 而其余保持在 chat 上,请为该对添加 `match.peer` 绑定;对匹配始终优先于渠道级规则。
- 如果你有一个渠道多个账户,请在绑定中添加 `accountId`(例如 `{ channel: "whatsapp", accountId: "personal" }`)。
- 要将单个私/群组路由到 Opus 而保持其余在 chat 上,请为该对等方添加 `match.peer` 绑定;对等方匹配始终优先于渠道级规则。
## 示例:同一渠道,一个对端路由到 Opus
## 示例:同一渠道,一个对等方到 Opus
WhatsApp 保持在快速智能体上,但将一个私路由到 Opus
保持 WhatsApp 在快速智能体上,但将一个私路由到 Opus
```json5
{
@@ -265,11 +265,11 @@ openclaw agents list --bindings
}
```
绑定始终优先,因此将它们放在渠道级规则之上。
等方绑定始终获胜,因此将它们放在渠道级规则之上。
## 绑定到 WhatsApp 群组的家庭智能体
一个专用家庭智能体绑定到单个 WhatsApp 群组,使用提及制和更严格的工具策略:
将专用家庭智能体绑定到单个 WhatsApp 群组,使用提及制和更严格的工具策略:
```json5
{
@@ -314,12 +314,12 @@ openclaw agents list --bindings
}
```
说明
注意事项
- 工具允许/拒绝列表针对的是**工具**而非 Skills。如果某个 Skills 需要运行二进制文件,请确保允许 `exec` 并且该二进制文件存在于沙箱中。
- 要实现更严格的制,设置 `agents.list[].groupChat.mentionPatterns` 并为渠道启用群组白名单
- 工具允许/拒绝列表是**工具**不是 Skills。如果 skill 需要运行二进制文件,请确保 `exec` 被允许且二进制文件存在于沙箱中。
- 对于更严格的制,设置 `agents.list[].groupChat.mentionPatterns` 并为渠道保持群组允许列表启用。
## 智能体沙箱和工具配置
## 智能体沙箱和工具配置
从 v2026.1.6 开始,每个智能体可以有自己的沙箱和工具限制:
@@ -331,7 +331,7 @@ openclaw agents list --bindings
id: "personal",
workspace: "~/.openclaw/workspace-personal",
sandbox: {
mode: "off", // 个人智能体不使用沙箱
mode: "off", // 个人智能体沙箱
},
// 无工具限制 - 所有工具可用
},
@@ -340,15 +340,15 @@ openclaw agents list --bindings
workspace: "~/.openclaw/workspace-family",
sandbox: {
mode: "all", // 始终沙箱隔离
scope: "agent", // 每智能体一个容器
scope: "agent", // 每智能体一个容器
docker: {
// 容器创建后的可选一次性设置
setupCommand: "apt-get update && apt-get install -y git curl",
},
},
tools: {
allow: ["read"], // 仅允许 read 工具
deny: ["exec", "write", "edit", "apply_patch"], // 拒绝其他工具
allow: ["read"], // 仅 read 工具
deny: ["exec", "write", "edit", "apply_patch"], // 拒绝其他
},
},
],
@@ -356,14 +356,17 @@ openclaw agents list --bindings
}
```
注意:`setupCommand` 位于 `sandbox.docker` 下,在容器创建时运行一次。当解析的 scope 为 `"shared"` 时,按智能体的 `sandbox.docker.*` 覆盖会被忽略。
注意:`setupCommand` 位于 `sandbox.docker` 下,在容器创建时运行一次。
当解析的 scope 为 `"shared"` 时,每智能体 `sandbox.docker.*` 覆盖会被忽略。
**优势**
**好处**
- **安全隔离**:限制不受信任智能体的工具
- **资源控制**:沙箱隔离特定智能体同时其他智能体在主机上运行
- **灵活策略**智能体设置不同权限
- **安全隔离**:限制不受信任智能体的工具
- **资源控制**:沙箱隔离特定智能体同时保持其他智能体在主机上
- **灵活策略**智能体不同权限
注意:`tools.elevated` 是**全局的**且基于发送者;不能按智能体配置。如果你需要按智能体的边界,请使用 `agents.list[].tools` 来拒绝 `exec`。对于群组定向,请使用 `agents.list[].groupChat.mentionPatterns`,以便 @提及能准确映射到目标智能体
注意:`tools.elevated` 是**全局的**且基于发送者;不能按智能体配置。
如果你需要每智能体边界,使用 `agents.list[].tools` 拒绝 `exec`
对于群组定向,使用 `agents.list[].groupChat.mentionPatterns` 使 @提及清晰地映射到目标智能体
[多智能体沙箱工具](/multi-agent-sandbox-tools)获取详细示例。
[多智能体沙箱工具](/multi-agent-sandbox-tools) 了解详细示例。
+40 -40
View File
@@ -1,99 +1,99 @@
---
read_when:
- 调试实例选项卡
- 调试实例标签页
- 排查重复或过期的实例行
- 更改 Gateway网关 WebSocket 连接或系统事件信标
summary: OpenClaw 在线状态条目生成、合并显示方式
- 更改 Gateway 网关 WS 连接或系统事件信标
summary: OpenClaw 在线状态条目如何生成、合并显示
title: 在线状态
x-i18n:
generated_at: "2026-02-01T20:23:31Z"
generated_at: "2026-02-03T07:46:37Z"
model: claude-opus-4-5
provider: pi
source_hash: c752c76a880878fed673d656db88beb5dbdeefff2491985127ad791521f97d00
source_path: concepts/presence.md
workflow: 14
workflow: 15
---
# 在线状态
OpenClaw"在线状态"是一个轻量级、尽力而为的视图,展示
OpenClaw"在线状态"是以下内容的轻量级、尽力而为的视图:
- **Gateway网关**身,以及
- **连接到 Gateway网关的客户端**(Mac 应用、WebChat、CLI 等)
- **Gateway 网关**身,以及
- **连接到 Gateway 网关的客户端**mac 应用、WebChat、CLI 等)
在线状态主要用于渲染 macOS 应用的**实例**选项卡,并为操作人员提供快速可视化
在线状态主要用于渲染 macOS 应用的**实例**标签页,并为运维人员提供快速可见性
## 在线状态字段(显示内容)
## 在线状态字段(显示内容)
在线状态条目是结构化对象,包含以下字段
在线状态条目是具有以下字段的结构化对象:
- `instanceId`(可选但强烈建议提供):稳定的客户端标识(通常 `connect.client.instanceId`
- `host`:人类可读的主机名
- `instanceId`(可选但强烈推荐):稳定的客户端身份(通常 `connect.client.instanceId`
- `host`:人类友好的主机名
- `ip`:尽力而为的 IP 地址
- `version`:客户端版本字符串
- `deviceFamily` / `modelIdentifier`:硬件提示信息
- `deviceFamily` / `modelIdentifier`:硬件提示
- `mode``ui``webchat``cli``backend``probe``test``node`...
- `lastInputSeconds`"上次用户输入的秒数"(如果已知)
- `lastInputSeconds`"上次用户输入以来的秒数"(如果已知)
- `reason``self``connect``node-connected``periodic`...
- `ts`:最后更新时间戳(自纪元以来的毫秒数)
## 生产者(在线状态来源)
## 生产者(在线状态来源)
在线状态条目由多个来源产生并进行**合并**。
在线状态条目由多个来源生成并**合并**。
### 1Gateway网关自身条目
### 1Gateway 网关自身条目
Gateway网关在启动时始终会创建一个"self"条目,这样即使在任何客户端连接之前,UI 也能显示 Gateway网关主机。
Gateway 网关始终在启动时植入一个"self"条目,这样即使在任何客户端连接之前,UI 也能显示 Gateway 网关主机。
### 2WebSocket 连接
每个 WebSocket 客户端都以 `connect` 请求开始。握手成功后,Gateway网关为该连接更新插入一个在线状态条目。
每个 WS 客户端都以 `connect` 请求开始。在成功握手后,Gateway 网关为该连接更新插入一个在线状态条目。
#### 为什么一次性 CLI 命令不会显示
CLI 通常只为短暂的一次性命令建立连接。为避免实例列表被频繁刷新`client.mode === "cli"` **不会**被转换为在线状态条目。
CLI 经常为短暂的一次性命令进行连接。为避免实例列表被刷屏`client.mode === "cli"` **不会**被转换为在线状态条目。
### 3`system-event` 信标
客户端可以通过 `system-event` 方法发送更丰富的周期性信标。Mac 应用使用此机制报告主机名、IP 和 `lastInputSeconds`
客户端可以通过 `system-event` 方法发送更丰富的周期性信标。mac 应用使用此方法报告主机名、IP 和 `lastInputSeconds`
### 4)节点连接(role: node
当节点通过 Gateway网关 WebSocket 以 `role: node` 连接时,Gateway网关为该节点更新插入一个在线状态条目(与其他 WebSocket 客户端流程相同)。
当节点通过 Gateway 网关 WebSocket 以 `role: node` 连接时,Gateway 网关为该节点更新插入一个在线状态条目(与其他 WS 客户端流程相同)。
## 合并去重规则(为什么 `instanceId` 很重要)
## 合并 + 去重规则(为什么 `instanceId` 很重要)
在线状态条目存储在单个内存映射中:
- 条目以**在线状态键**为索引。
- 最佳键是稳定的 `instanceId`(来自 `connect.client.instanceId`),在重启后保持不变
- 条目以**在线状态键**为索引。
- 最佳键是稳定的 `instanceId`(来自 `connect.client.instanceId`),在重启后仍然有效
- 键不区分大小写。
如果客户端在没有稳定 `instanceId` 的情况下重新连接,可能会显示为**重复**行。
如果客户端在没有稳定 `instanceId` 的情况下重新连接,可能会显示为**重复**行。
## TTL 和大小限制
## TTL 和有界大小
在线状态是有意设计为临时性的:
在线状态是有意设计为短暂的:
- **TTL**超过 5 分钟的条目将被清除
- **最大条目数:**200优先丢弃最旧的条目
- **TTL** 超过 5 分钟的条目会被修剪
- **最大条目数:** 200最旧的优先删除
确保列表保持新鲜避免无限制的内存增长。
使列表保持新鲜避免无限制的内存增长。
## 远程/隧道注意事项(local loopback IP
## 远程/隧道注意事项(回环 IP
当客户端通过 SSH 隧道/本地端口转发连接时,Gateway网关可能会远程地址识别`127.0.0.1`。为避免覆盖客户端报告的有效 IPlocal loopback 远程地址会被忽略。
当客户端通过 SSH 隧道/本地端口转发连接时,Gateway 网关可能会看到远程地址为 `127.0.0.1`。为避免覆盖客户端报告的有效 IP回环远程地址会被忽略。
## 消费者
### macOS 实例选项卡
### macOS 实例标签页
macOS 应用渲染 `system-presence` 的输出,并根据最后更新的时间显示小型状态指示器(活跃/空闲/过期)。
macOS 应用渲染 `system-presence` 的输出,并根据最后更新的时间应用一个小的状态指示器(活跃/空闲/过期)。
## 调试技巧
- 要查看原始列表,对 Gateway网关调用 `system-presence`
- 如果看到重复条目
- 确认客户端在握手中发送稳定的 `client.instanceId`
- 要查看原始列表,对 Gateway 网关调用 `system-presence`
- 如果看到重复
- 确认客户端在握手中发送稳定的 `client.instanceId`
- 确认周期性信标使用相同的 `instanceId`
- 检查连接派生的条目是否缺少 `instanceId`此时重复是预期行为
- 检查连接派生的条目是否缺少 `instanceId`这种情况下重复是预期
+34 -34
View File
@@ -1,53 +1,53 @@
---
read_when:
- 更改自动回复执行或并发机制
summary: 序列化入站自动回复运行的命令队列设计
- 更改自动回复执行或并发设置时
summary: 用于序列化入站自动回复运行的命令队列设计
title: 命令队列
x-i18n:
generated_at: "2026-02-01T20:23:48Z"
generated_at: "2026-02-03T10:05:28Z"
model: claude-opus-4-5
provider: pi
source_hash: 2104c24d200fb4f9620e52a19255cd614ababe19d78f3ee42936dc6d0499b73b
source_path: concepts/queue.md
workflow: 14
workflow: 15
---
# 命令队列(2026-01-16
我们通过一个轻量的进程内队列序列化入站自动回复运行(所有渠道),以防止多个智能体运行发生冲突,同时仍允许跨会话的安全并行。
我们通过一个小型进程内队列序列化入站自动回复运行(所有渠道),以防止多个智能体运行发生冲突,同时仍允许跨会话的安全并行。
## 原因
## 为什么需要
- 自动回复运行可能开销很大(LLM 调用),当多条入站消息几乎同时到达时可能发生冲突。
- 序列化可以避免争共享资源(会话文件、日志、CLI 标准输入),并降低触发上游速率限制的概率
- 自动回复运行可能开销很大(LLM 调用),当多条入站消息接近同时到达时可能发生冲突。
- 序列化可以避免争共享资源(会话文件、日志、CLI stdin),并降低上游速率限制的可能性
## 工作原理
- 一个支持通道感知的 FIFO 队列以可配置的并发上限逐通道排空(未配置的通道默认为 1;main 默认为 4subagent 默认为 8)。
- `runEmbeddedPiAgent` 按**会话键**(通道 `session:<key>`入队,以保证每个会话同一时间只有一个活运行。
- 每个会话运行随后被排入**全局通道**(默认为 `main`),因此整体并行度受 `agents.defaults.maxConcurrent` 限制。
- 启用详细日志时,如果排队运行在启动前等待超过约 2 秒,会发出一条简短通知。
- 输入指示器在入队时仍会立即触发(当渠道支持时),因此在等待期间用户体验不受影响。
- 一个支持通道感知的 FIFO 队列以可配置的并发上限排空每个通道(未配置的通道默认为 1;main 默认为 4subagent 为 8)。
- `runEmbeddedPiAgent` 按**会话键**入队(通道 `session:<key>`),以保证每个会话只有一个活运行。
- 然后每个会话运行被排入**全局通道**(默认为 `main`),因此整体并行度受 `agents.defaults.maxConcurrent` 限制。
- 启用详细日志时,如果排队运行在开始前等待超过约 2 秒,会发出简短通知。
- 输入指示器在入队时立即触发(当渠道支持时),因此在等待轮次时用户体验不受影响。
## 队列模式(按渠道)
入站消息可以引导当前运行、等待后续轮次,或两者兼顾:
- `steer`:立即注入当前运行(在下一个工具边界后取消待执行的工具调用)。如果未在流式传输,则回退 followup。
- `followup`:在当前运行结束后排队等待下一个智能体轮次。
- `steer`:立即注入当前运行(在下一个工具边界后取消待处理的工具调用)。如果未在流式传输,则回退 followup。
- `followup`:在当前运行结束后下一个智能体轮次入队
- `collect`:将所有排队消息合并为**单个**后续轮次(默认)。如果消息针对不同的渠道/线程,它们会单独排空以保留路由。
- `steer-backlog`(又名 `steer+backlog`):立即引导**并**保留消息用于后续轮次。
- `interrupt`(旧版):中止该会话的活运行,然后运行最新消息。
- `queue`(旧版别名):等同于 `steer`
- `steer-backlog`(又名 `steer+backlog`):现在引导**并**保留消息用于后续轮次。
- `interrupt`(旧版):中止该会话的活运行,然后运行最新消息。
- `queue`(旧版别名): `steer` 相同
steer-backlog 意味着引导运行之后你还能获得后续响应,因此流式传输界面可能看起来像重复内容。如果希望每条入站消息只获得一次响应,请优先使用 `collect`/`steer`
发送 `/queue collect` 作为独立命令(按会话生效),或设置 `messages.queue.byChannel.discord: "collect"`
steer-backlog 意味着你可以在被引导运行之后获得后续响应,因此流式传输界面可能看起来像重复。如果希望每条入站消息只有一个响应,请优先使用 `collect`/`steer`
发送 `/queue collect` 作为独立命令(按会话或设置 `messages.queue.byChannel.discord: "collect"`
默认值(配置中未设置时):
- 所有界面 → `collect`
通过 `messages.queue` 进行全局或按渠道配置:
通过 `messages.queue` 全局或按渠道配置:
```json5
{
@@ -65,30 +65,30 @@ steer-backlog 意味着在引导运行之后你还能获得后续响应,因此
## 队列选项
选项适用于 `followup``collect``steer-backlog`(以及 `steer` 回退 followup 时):
选项适用于 `followup``collect``steer-backlog`(以及 `steer` 回退 followup 时):
- `debounceMs`:在启动后续轮次前等待静默(防止"继续,继续"的情况)。
- `debounceMs`:在开始后续轮次前等待静默(防止"继续,继续")。
- `cap`:每个会话的最大排队消息数。
- `drop`:溢出策略(`old``new``summarize`)。
summarize 保留一个被丢弃消息的简短要点列表,并将其作为合成的后续提示注入。
summarize 保留被丢弃消息的简短要点列表,并将其作为合成的后续提示注入。
默认值:`debounceMs: 1000``cap: 20``drop: summarize`
## 按会话覆盖
- 发送 `/queue <mode>` 作为独立命令,可将该模式存储到当前会话
- 选项可以组合使用`/queue collect debounce:2s cap:25 drop:summarize`
- 发送 `/queue <mode>` 作为独立命令,为当前会话存储该模式
- 选项可以组合:`/queue collect debounce:2s cap:25 drop:summarize`
- `/queue default``/queue reset` 清除会话覆盖。
## 作用范围保证
## 范围保证
- 适用于所有使用 Gateway网关回复管道的入站渠道的自动回复智能体运行(WhatsApp 网页版、Telegram、Slack、Discord、Signal、iMessage、网页聊天等)。
- 默认通道(`main`在进程范围内适用于入站消息和主心跳;设置 `agents.defaults.maxConcurrent` 以允许多个会话并行。
- 可能存在其他通道(如 `cron``subagent`),以便后台任务可以并行运行而不阻塞入站回复。
- 按会话通道保证同一时间只有一个智能体运行触给定会话。
- 无外部依赖或后台工作线程;纯 TypeScript + Promise 实现
- 适用于所有使用 Gateway 网关回复管道的入站渠道的自动回复智能体运行(WhatsApp 网页版、Telegram、Slack、Discord、Signal、iMessage、网页聊天等)。
- 默认通道(`main`对入站 + 主心跳是进程范围的;设置 `agents.defaults.maxConcurrent` 以允许多个会话并行。
- 可能存在额外的通道(`cron``subagent`),以便后台任务可以并行运行而不阻塞入站回复。
- 按会话通道保证一次只有一个智能体运行触给定会话。
- 无外部依赖或后台工作线程;纯 TypeScript + promises
## 故障排除
- 如果命令似乎卡住,启用详细日志并查找 "queued for …ms" 行,以确认队列正在正常排空。
- 如果需要查看队列深度,启用详细日志并观察队列计时行。
- 如果命令似乎卡住,启用详细日志并查找"queued for …ms"以确认队列正在排空。
- 如果需要查看队列深度,启用详细日志并观察队列计时行。
+38 -38
View File
@@ -1,72 +1,72 @@
---
read_when:
- 你想减少工具输出导致的 LLM 上下文增长
- 你正在调 agents.defaults.contextPruning
summary: 会话裁剪:通过修剪工具结果减少上下文膨胀
- 你正在调 agents.defaults.contextPruning
summary: 会话剪枝:工具结果修剪以减少上下文膨胀
x-i18n:
generated_at: "2026-02-01T20:23:53Z"
generated_at: "2026-02-03T07:46:35Z"
model: claude-opus-4-5
provider: pi
source_hash: 9b0aa2d1abea7050ba848a2db038ccc3e6e2d83c6eb4e3843a2ead0ab847574a
source_path: concepts/session-pruning.md
workflow: 14
workflow: 15
---
# 会话
# 会话剪
会话剪在每次 LLM 调用之前修剪内存上下文中**旧工具结果**。它**不会**重写磁盘上的会话历史(`*.jsonl`)。
会话剪在每次 LLM 调用之前内存上下文中修剪**旧工具结果**。它**不会**重写磁盘上的会话历史(`*.jsonl`)。
## 运行时机
- 当启用 `mode: "cache-ttl"` 且该会话的次 Anthropic 调用时间超过 `ttl`触发
- 当启用 `mode: "cache-ttl"` 且该会话的最后一次 Anthropic 调用早于 `ttl` 时。
- 仅影响该请求发送给模型的消息。
- 仅对 Anthropic API 调用(以及 OpenRouter Anthropic 模型)生效。
- 为获得最佳效果,请将 `ttl` 与模型 `cacheControlTtl` 保持一致
- 剪后,TTL 窗口会重置,后续请求将继续使用缓存直到 `ttl` 再次过期。
- 仅对 Anthropic API 调用( OpenRouter Anthropic 模型)生效。
- 为获得最佳效果,请将 `ttl`你的模型 `cacheControlTtl` 匹配
-后,TTL 窗口会重置,因此后续请求会保持缓存直到 `ttl` 再次过期。
## 智能默认值(Anthropic
- **OAuth 或 setup-token** 配置文件:启用 `cache-ttl` 裁剪,并将心跳设置为 `1h`
- **API 密钥**配置文件:启用 `cache-ttl` 剪,将心跳设置为 `30m`,并将 Anthropic 模型的 `cacheControlTtl` 默认`1h`
- **OAuth 或 setup-token** 配置文件:启用 `cache-ttl` 剪枝并将心跳设置为 `1h`
- **API 密钥**配置文件:启用 `cache-ttl`,将心跳设置为 `30m`,并将 Anthropic 模型的 `cacheControlTtl` 默认为 `1h`
- 如果你显式设置了这些值中的任何一个,OpenClaw **不会**覆盖它们。
## 改善效果(成本 + 缓存行为)
## 改进内容(成本 + 缓存行为)
- **为什么要剪:** Anthropic 提示缓存仅在 TTL 内生效。如果会话空闲超过 TTL,下一请求重新缓存完整提示,除非你先对其进行修剪。
- **哪些费用会降低** 剪减少了 TTL 过期后首次请求的 **cacheWrite** 大小。
- **为什么 TTL 重置很重要:** 裁剪运行,缓存窗口会重置,因此后续请求可以用新缓存的提示,而不是再次重新缓存完整历史。
- **它不做什么:** 裁剪不会增加令牌或"倍"成本;它只改变 TTL 过期后首次请求缓存内容。
- **为什么要剪** Anthropic 提示缓存仅在 TTL 内适用。如果会话空闲超过 TTL,下一请求重新缓存完整提示,除非你先修剪
- **什么变得更便宜** 剪减少了 TTL 过期后第一个请求的 **cacheWrite** 大小。
- **为什么 TTL 重置很重要:** 一旦剪枝运行,缓存窗口会重置,因此后续请求可以用新缓存的提示,而不是再次重新缓存完整历史。
- **它不做什么:** 剪枝不会添加 token 或"倍"成本;它只改变 TTL 后第一个请求缓存内容。
## 可裁剪的内容
## 可以剪枝的内容
- `toolResult` 消息。
- 用户助手消息**永远不会**被修改。
- 最后 `keepLastAssistants` 条助手消息受保护;该截止点之后的工具结果不会被剪。
- 如果助手消息数量不足以确定截止点,则跳过剪。
- 包含**图块**的工具结果会被跳过(永远不会被修剪/清除)。
-`toolResult` 消息。
- 用户 + 助手消息**永远不会**被修改。
- 最后 `keepLastAssistants` 条助手消息受保护;该截止点之后的工具结果不会被剪
- 如果没有足够的助手消息来确定截止点,则跳过剪
- 包含**图块**的工具结果会被跳过(永修剪/清除)。
## 上下文窗口估算
剪使用估算的上下文窗口(字符令牌数 × 4)。基础窗口按以下顺序解析:
使用估算的上下文窗口(字符 ≈ token × 4)。基础窗口按以下顺序解析:
1. `models.providers.*.models[].contextWindow` 覆盖
2. 模型定义中的 `contextWindow`(来自模型注册表)。
3. 默认 `200000` 令牌
1. `models.providers.*.models[].contextWindow` 覆盖。
2. 模型定义 `contextWindow`(来自模型注册表)。
3. 默认 `200000` token
如果设置了 `agents.defaults.contextTokens`,它将为解析窗口的上限(最小值)。
如果设置了 `agents.defaults.contextTokens`,它将被视为解析窗口的上限(最小值)。
## 模式
### cache-ttl
- 仅当次 Anthropic 调用时间超过 `ttl`(默认 `5m`)时才运行剪。
- 仅当最后一次 Anthropic 调用早于 `ttl`(默认 `5m`)时才运行剪
- 运行时:与之前相同的软修剪 + 硬清除行为。
## 软裁剪与硬裁
## 软剪枝 vs 硬剪枝
- **软修剪**:仅针对超大的工具结果。
- 保留头部尾部,插入 `...`,并附加一包含原始大小的说明
- 跳过包含图块的结果。
- **软修剪**:仅用于过大的工具结果。
- 保留头部 + 尾部,插入 `...`,并附加一包含原始大小的注释
- 跳过包含图块的结果。
- **硬清除**:用 `hardClear.placeholder` 替换整个工具结果。
## 工具选择
@@ -78,8 +78,8 @@ x-i18n:
## 与其他限制的交互
- 内置工具已经截断自的输出;会话剪是一个额外的保护层,防止长时间运行的对话在模型上下文中累过多的工具输出。
- 压缩是独立的:压缩进行摘要并持久化,裁剪则是每请求的临时操作。参 [/concepts/compaction](/concepts/compaction)。
- 内置工具已经截断自的输出;会话剪是一个额外的层,防止长时间运行的聊天在模型上下文中累过多的工具输出。
- 压缩是独立的:压缩进行总结并持久化,剪枝是每请求的临时操作。参 [/concepts/compaction](/concepts/compaction)。
## 默认值(启用时)
@@ -103,7 +103,7 @@ x-i18n:
}
```
启用 TTL 感知剪:
启用 TTL 感知剪
```json5
{
@@ -113,7 +113,7 @@ x-i18n:
}
```
将裁剪限制为特定工具:
限制剪枝到特定工具:
```json5
{
@@ -126,4 +126,4 @@ x-i18n:
}
```
配置参考:[Gateway网关配置](/gateway/configuration)
配置参考:[Gateway 网关配置](/gateway/configuration)
+60 -60
View File
@@ -1,20 +1,20 @@
---
read_when:
- 添加或修改会话工具
summary: 智能体会话工具:列出会话、获取历史记录和发送跨会话消息
- 添加或修改会话工具
summary: 用于列出会话、获取历史记录和发送跨会话消息的智能体会话工具
title: 会话工具
x-i18n:
generated_at: "2026-02-01T20:24:08Z"
generated_at: "2026-02-03T07:46:54Z"
model: claude-opus-4-5
provider: pi
source_hash: cb6e0982ebf507bcf9de4bb17719759c2b6d3e519731c845580a55279084e4c8
source_path: concepts/session-tool.md
workflow: 14
workflow: 15
---
# 会话工具
目标:提供小型、不易误用的工具集,使智能体能够列出会话、获取历史记录以及向其他会话发送消息。
目标:小型、不易误用的工具集,使智能体能够列出会话、获取历史记录并向另一个会话发送消息。
## 工具名称
@@ -25,62 +25,62 @@ x-i18n:
## 键模型
-私聊桶始终使用字面键 `"main"`(解析为当前智能体的主键)。
- 群聊使用 `agent:<agentId>:<channel>:group:<id>``agent:<agentId>:<channel>:channel:<id>`(传完整键)。
-直接聊天桶始终字面键 `"main"`(解析为当前智能体的主键)。
- 群聊使用 `agent:<agentId>:<channel>:group:<id>``agent:<agentId>:<channel>:channel:<id>`(传完整键)。
- 定时任务使用 `cron:<job.id>`
- 钩子使用 `hook:<uuid>`,除非显式设置。
- 节点会话使用 `node-<nodeId>`,除非显式设置。
- Hooks 使用 `hook:<uuid>`,除非明确设置。
- Node 会话使用 `node-<nodeId>`,除非明确设置。
`global``unknown` 是保留值,永远不会被列出。如果 `session.scope = "global"`,我们会将其别名为 `main` 所有工具使用,这样调用永远不到 `global`
`global``unknown` 是保留值,永远不会被列出。如果 `session.scope = "global"`,我们会将其别名为 `main` 用于所有工具,这样调用永远不会看`global`
## sessions_list
以行数组形式列出会话
将会话列为行数组
参数:
- `kinds?: string[]` 过滤器:`"main" | "group" | "cron" | "hook" | "node" | "other"` 的任意组合
- `limit?: number` 最大行数(默认:服务器默认值,限如 200
- `activeMinutes?: number`返回 N 分钟内更新的会话
- `messageLimit?: number` 0 = 不返回消息(默认 0);>0 = 包含最 N 条消息
- `kinds?: string[]` 过滤器:`"main" | "group" | "cron" | "hook" | "node" | "other"` 的任意一个
- `limit?: number` 最大行数(默认:服务器默认值,限如 200
- `activeMinutes?: number` N 分钟内更新的会话
- `messageLimit?: number` 0 = 消息(默认 0);>0 = 包含最 N 条消息
行为:
- `messageLimit > 0` 时会获取每个会话的 `chat.history` 并包含最 N 条消息。
- 列表输出中过滤工具结果;使用 `sessions_history` 获取工具消息。
- 在**沙箱隔离**的智能体会话中运行时,会话工具默认为**仅生成可见**(见下文)。
- `messageLimit > 0` 获取每个会话的 `chat.history` 并包含最 N 条消息。
- 工具结果在列表输出中过滤;使用 `sessions_history` 获取工具消息。
- 在**沙箱隔离**的智能体会话中运行时,会话工具默认为**仅生成可见**(见下文)。
行结构(JSON):
- `key`:会话键(字符串)
- `kind``main | group | cron | hook | node | other`
- `channel``whatsapp | telegram | discord | signal | imessage | webchat | internal | unknown`
- `displayName`(群组显示标签,如可用
- `displayName`如果可用的群组显示标签)
- `updatedAt`(毫秒)
- `sessionId`
- `model``contextTokens``totalTokens`
- `thinkingLevel``verboseLevel``systemSent``abortedLastRun`
- `sendPolicy`(会话覆盖,如已设置
- `sendPolicy`如果设置的会话覆盖)
- `lastChannel``lastTo`
- `deliveryContext`(规范化 `{ channel, to, accountId }`,如可用
- `transcriptPath`根据存储目录 + sessionId 推导的尽力路径)
- `deliveryContext`可用时的规范化 `{ channel, to, accountId }`
- `transcriptPath`存储目录 + sessionId 派生的尽力路径)
- `messages?`(仅当 `messageLimit > 0` 时)
## sessions_history
获取个会话的对话记录。
获取个会话的记录。
参数:
- `sessionKey`(必;接受会话键或来自 `sessions_list``sessionId`
- `limit?: number` 最大消息数(服务器限制上限
- `sessionKey`(必;接受会话键或来自 `sessions_list``sessionId`
- `limit?: number` 最大消息数(服务器限制)
- `includeTools?: boolean`(默认 false
行为:
- `includeTools=false` 过滤 `role: "toolResult"` 消息。
- 以原始对话记录格式返回消息数组。
-传入 `sessionId` 时,OpenClaw 将其解析为应的会话键(缺失的 ID 会报错)。
- `includeTools=false` 过滤 `role: "toolResult"` 消息。
- 以原始记录格式返回消息数组。
-给定 `sessionId` 时,OpenClaw 将其解析为应的会话键(缺失的 id 会报错)。
## sessions_send
@@ -88,8 +88,8 @@ x-i18n:
参数:
- `sessionKey`(必;接受会话键或来自 `sessions_list``sessionId`
- `message`(必
- `sessionKey`(必;接受会话键或来自 `sessions_list``sessionId`
- `message`(必
- `timeoutSeconds?: number`(默认 >0;0 = 即发即忘)
行为:
@@ -98,28 +98,28 @@ x-i18n:
- `timeoutSeconds > 0`:等待最多 N 秒完成,然后返回 `{ runId, status: "ok", reply }`
- 如果等待超时:`{ runId, status: "timeout", error }`。运行继续;稍后调用 `sessions_history`
- 如果运行失败:`{ runId, status: "error", error }`
-投递在主运行完成后运行,属于尽力而为;`status: "ok"` 不保证通知已成功投递。
- 通过 Gateway网关 `agent.wait`(服务器端)等待,因此重连不会中断等待。
- 智能体消息上下文会注入到主运行
- 主运行完成后,OpenClaw 运行**回复往返循环**
- 第 2 轮及后在请求和目标智能体之间交替。
- 回复 `REPLY_SKIP` 停止来回往返
-投递在主运行完成后运行,且为尽力而为;`status: "ok"` 不保证通告已投递。
- 通过 Gateway 网关 `agent.wait`(服务器端)等待,因此重连不会丢失等待。
- 智能体到智能体的消息上下文会主运行注入
- 主运行完成后,OpenClaw 运行**回复循环**
- 第 2 轮及后在请求和目标智能体之间交替。
- 精确回复 `REPLY_SKIP` 停止来回。
- 最大轮数为 `session.agentToAgent.maxPingPongTurns`05,默认 5)。
- 循环结束后,OpenClaw 运行**智能体间通知步骤**(仅目标智能体):
- 回复 `ANNOUNCE_SKIP` 保持静默。
- 其他任何回复都会发送到目标渠道。
-步骤包原始请求 + 第 1 轮回复 + 最新的往返回复。
- 循环结束后,OpenClaw 运行**智能体到智能体通告步骤**(仅目标智能体):
- 精确回复 `ANNOUNCE_SKIP` 保持静默。
- 任何其他回复都会发送到目标渠道。
-步骤包原始请求 + 第 1 轮回复 + 最新的来回回复。
## Channel 字段
- 对于群组,`channel` 是会话条目上记录的渠道。
- 对于私聊`channel``lastChannel` 映射。
- 对于定时任务/钩子/节点`channel` `internal`
- 如果缺失,`channel` `unknown`
- 对于直接聊天`channel``lastChannel` 映射。
- 对于 cron/hook/node`channel` `internal`
- 如果缺失,`channel` `unknown`
## 安全 / 发送策略
基于策略的按渠道/聊天类型阻止(按会话 ID)。
基于策略的按渠道/聊天类型阻止(不是按会话 id)。
```json
{
@@ -144,45 +144,45 @@ x-i18n:
执行点:
- `chat.send` / `agent`Gateway网关)
- `chat.send` / `agent`Gateway 网关)
- 自动回复投递逻辑
## sessions_spawn
在隔离会话中生成子智能体运行,并将结果通回请求方的聊天渠道。
在隔离会话中生成子智能体运行,并将结果通回请求聊天渠道。
参数:
- `task`(必
- `task`(必
- `label?`(可选;用于日志/UI
- `agentId?`(可选;如允许,在另一个智能体 ID 下生成)
- `agentId?`(可选;如允许,在另一个智能体 id 下生成)
- `model?`(可选;覆盖子智能体模型;无效值会报错)
- `runTimeoutSeconds?`(默认 0;设置后,N 秒后中止子智能体运行)
- `runTimeoutSeconds?`(默认 0;设置时,在 N 秒后中止子智能体运行)
- `cleanup?``delete|keep`,默认 `keep`
允许列表:
- `agents.list[].subagents.allowAgents`允许通过 `agentId` 使用的智能体 ID 列表(`["*"]` 允许任意)。默认:仅请求智能体。
- `agents.list[].subagents.allowAgents`:通过 `agentId` 允许的智能体 id 列表(`["*"]` 允许任意)。默认:仅请求智能体。
发现:
- 使用 `agents_list` 发现哪些智能体 ID 可用于 `sessions_spawn`
- 使用 `agents_list` 发现哪些智能体 id 允许用于 `sessions_spawn`
行为:
- 启动一个新的 `agent:<agentId>:subagent:<uuid>` 会话,设置 `deliver: false`
- 使用 `deliver: false` 启动新的 `agent:<agentId>:subagent:<uuid>` 会话。
- 子智能体默认使用完整工具集**减去会话工具**(可通过 `tools.subagents.tools` 配置)。
- 子智能体不允许调用 `sessions_spawn`不允许子智能体生成子智能体)。
- 子智能体不允许调用 `sessions_spawn`子智能体子智能体生成)。
- 始终非阻塞:立即返回 `{ status: "accepted", runId, childSessionKey }`
- 完成后,OpenClaw 运行子智能体**通步骤**并将结果发布到请求方的聊天渠道。
- 在通步骤中回复 `ANNOUNCE_SKIP` 保持静默。
-回复规范化为 `Status`/`Result`/`Notes``Status` 来自运行时结果(模型文本)。
- 子智能体会话在 `agents.defaults.subagents.archiveAfterMinutes`(默认:60后自动归档
-回复包含统计行(运行时间、token 数、sessionKey/sessionId、对话记录路径和可选费用)。
- 完成后,OpenClaw 运行子智能体**通步骤**并将结果发布到请求聊天渠道。
- 在通步骤中精确回复 `ANNOUNCE_SKIP` 保持静默。
-回复规范化为 `Status`/`Result`/`Notes``Status` 来自运行时结果(不是模型文本)。
- 子智能体会话在 `agents.defaults.subagents.archiveAfterMinutes` 后自动归档(默认:60)。
-回复包含统计行(运行时间、token 数、sessionKey/sessionId、记录路径和可选成本)。
## 沙箱会话可见性
沙箱隔离的会话可以使用会话工具,但默认只能看到通过 `sessions_spawn` 生成的会话。
沙箱隔离的会话可以使用会话工具,但默认情况下它们只能看到通过 `sessions_spawn` 生成的会话。
配置:
@@ -191,7 +191,7 @@ x-i18n:
agents: {
defaults: {
sandbox: {
// 默认: "spawned"
// 默认"spawned"
sessionToolsVisibility: "spawned", // 或 "all"
},
},
+62 -62
View File
@@ -1,88 +1,88 @@
---
read_when:
- 修改会话处理或存储
- 修改会话处理或存储
summary: 聊天的会话管理规则、键和持久化
title: 会话管理
x-i18n:
generated_at: "2026-02-01T20:24:31Z"
generated_at: "2026-02-03T07:47:44Z"
model: claude-opus-4-5
provider: pi
source_hash: 147c8d1a4b6b4864cb16ad942feba80181b6b0e29afa765e7958f8c2483746b5
source_path: concepts/session.md
workflow: 14
workflow: 15
---
# 会话管理
OpenClaw 将**每个智能体一个私聊会话**视为主会话。私聊归并到 `agent:<agentId>:<mainKey>`(默认 `main`),而群组/频道聊天拥有各自独立的键。`session.mainKey` 会被遵循。
OpenClaw 将**每个智能体一个直接聊天会话**视为主会话。直接聊天折叠为 `agent:<agentId>:<mainKey>`(默认 `main`),而群组/频道聊天获得各自的键。`session.mainKey` 会被遵循。
使用 `session.dmScope` 控制**私信**的分组方式
使用 `session.dmScope` 控制**私信**如何分组
- `main`(默认):所有私信共享主会话以保持连续性。
- `per-peer`:按发送者 ID 跨渠道隔离。
- `per-peer`跨渠道按发送者 ID 隔离。
- `per-channel-peer`:按渠道 + 发送者隔离(推荐用于多用户收件箱)。
- `per-account-channel-peer`:按账 + 渠道 + 发送者隔离(推荐用于多账收件箱)。
使用 `session.identityLinks` 将带提供商前缀的对 ID 映射到规范身份,这样在使用 `per-peer``per-channel-peer``per-account-channel-peer` 时,同一个人可以跨渠道共享私信会话。
- `per-account-channel-peer`:按账 + 渠道 + 发送者隔离(推荐用于多账收件箱)。
使用 `session.identityLinks` 将带提供商前缀的对 ID 映射到规范身份,这样在使用 `per-peer``per-channel-peer``per-account-channel-peer` 时,同一个人可以跨渠道共享私信会话。
## Gateway网关是权威数据源
## Gateway 网关是唯一数据源
所有会话状态均由 **Gateway网关**"主" OpenClaw管理。UI 客户端(macOS 应用、WebChat 等)必须向 Gateway网关查询会话列表和令牌计数,而不是读取本地文件。
所有会话状态都**由 Gateway 网关拥有**"主" OpenClaw)。UI 客户端(macOS 应用、WebChat 等)必须向 Gateway 网关查询会话列表和令牌计数,而不是读取本地文件。
- 在**远程模式**下,你关心的会话存储位于远程 Gateway网关主机上,而不是你的 Mac 上。
- UI 中显示的令牌计数来自 Gateway网关存储字段(`inputTokens``outputTokens``totalTokens``contextTokens`)。客户端不会解析 JSONL 记录来"修正"总数。
- 在**远程模式**下,你关心的会话存储位于远程 Gateway 网关主机上,而不是你的 Mac 上。
- UI 中显示的令牌计数来自 Gateway 网关存储字段(`inputTokens``outputTokens``totalTokens``contextTokens`)。客户端不会解析 JSONL 对话记录来"修正"总数。
## 状态存储位置
- 在 **Gateway网关主机**上:
- 在 **Gateway 网关主机**上:
- 存储文件:`~/.openclaw/agents/<agentId>/sessions/sessions.json`(每个智能体)。
- 对话记录:`~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl`Telegram 话题会话使用 `.../<SessionId>-topic-<threadId>.jsonl`)。
- 存储是一个 `sessionKey -> { sessionId, updatedAt, ... }` 的映射。删除条目是安全的;它们会按需重新创建。
- 群组条目可能包含 `displayName``channel``subject``room``space`,用于在 UI 中标记会话。
- 会话条目包含 `origin` 元数据(标签 + 路由提示),以便 UI 能够解释会话的来源。
- OpenClaw **不**读取旧版 Pi/Tau 会话文件夹。
- 存储是一个映射 `sessionKey -> { sessionId, updatedAt, ... }`。删除条目是安全的;它们会按需重新创建。
- 群组条目可能包含 `displayName``channel``subject``room``space`在 UI 中标记会话。
- 会话条目包含 `origin` 元数据(标签 + 路由提示),以便 UI 可以解释会话的来源。
- OpenClaw **不**读取旧版 Pi/Tau 会话文件夹。
## 会话修剪
OpenClaw 默认在 LLM 调用之前从内存上下文中修剪**旧的工具结果**。
这**不会**重写 JSONL 历史记录。参见 [/concepts/session-pruning](/concepts/session-pruning)。
默认情况下,OpenClaw 在 LLM 调用之前从内存上下文中修剪**旧的工具结果**。
这**不会**重写 JSONL 历史记录。参见 [/concepts/session-pruning](/concepts/session-pruning)。
## 压缩前记忆刷
## 压缩前记忆刷
当会话接近自动压缩时,OpenClaw 可以运行一**静默记忆刷**轮次,提醒模型将持久笔记写入磁盘。这仅在工作区可写时运行。参见[记忆](/concepts/memory)和[压缩](/concepts/compaction)。
当会话接近自动压缩时,OpenClaw 可以运行一**静默记忆刷**轮次,提醒模型将持久笔记写入磁盘。这仅在工作区可写时运行。参见[记忆](/concepts/memory)和[压缩](/concepts/compaction)。
## 传输层 → 会话键的映射
## 传输会话键的映射
- 私聊遵循 `session.dmScope`(默认 `main`)。
- `main``agent:<agentId>:<mainKey>`(跨设备/渠道保持连续性)。
- 多个电话号码和渠道可以映射到同一个智能体主键;它们充当一个对话的传输通道。
- 直接聊天遵循 `session.dmScope`(默认 `main`)。
- `main``agent:<agentId>:<mainKey>`(跨设备/渠道连续性)。
- 多个电话号码和渠道可以映射到同一个智能体主键;它们作为进入同一个对话的传输通道。
- `per-peer``agent:<agentId>:dm:<peerId>`
- `per-channel-peer``agent:<agentId>:<channel>:dm:<peerId>`
- `per-account-channel-peer``agent:<agentId>:<channel>:<accountId>:dm:<peerId>`accountId 默认为 `default`)。
- 如果 `session.identityLinks` 匹配带提供商前缀的对 ID(例如 `telegram:123`),规范键替换 `<peerId>`使同一个人跨渠道共享会话。
-隔离状态:`agent:<agentId>:<channel>:group:<id>`(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
- Telegram 论坛话题在群组 ID 后附加 `:topic:<threadId>`实现隔离。
- 旧版 `group:<id>` 键仍被识别以支持迁移。
- 入站上下文可能仍使用 `group:<id>`;渠道从 `Provider` 推断并规范化为 `agent:<agentId>:<channel>:group:<id>` 的规范形式。
- 如果 `session.identityLinks` 匹配带提供商前缀的对 ID(例如 `telegram:123`),规范键替换 `<peerId>`这样同一个人可以跨渠道共享会话。
-组聊天隔离状态:`agent:<agentId>:<channel>:group:<id>`(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
- Telegram 论坛话题在群组 ID 后附加 `:topic:<threadId>`进行隔离。
- 旧版 `group:<id>` 键仍被识别以进行迁移。
- 入站上下文可能仍使用 `group:<id>`;渠道从 `Provider` 推断并规范化为规范的 `agent:<agentId>:<channel>:group:<id>` 形式。
- 其他来源:
- 定时任务:`cron:<job.id>`
- Webhook`hook:<uuid>`(除非由 hook 显式设置)
- Webhooks`hook:<uuid>`(除非由 hook 显式设置)
- 节点运行:`node-<nodeId>`
## 生命周期
- 重置策略:会话持续复用直到过期,过期在下一条入站消息时评估。
- 每日重置:默认为 **Gateway网关主机本地时间凌晨 4:00**。当会话的最后更新早于最近一次每日重置时间时,会话即为过期。
- 空闲重置(可选):`idleMinutes` 添加一个滑动空闲窗口。当同时配置每日重置和空闲重置时,**先到期的那个**强制创建新会话。
- 旧版仅空闲模式:如果设置了 `session.idleMinutes` 没有任何 `session.reset`/`resetByType` 配置,OpenClaw 会保持仅空闲模式以向后兼容。
- 按类型覆盖(可选):`resetByType` 允许你 `dm``group``thread` 会话覆盖策略(thread = Slack/Discord 线程、Telegram 话题、连接器提供的 Matrix 线程)。
- 按渠道覆盖(可选):`resetByChannel` 覆盖特定渠道的重置策略(适用于该渠道的所有会话类型,优先级高`reset`/`resetByType`)。
- 重置触发器:精确的 `/new``/reset`(加上 `resetTriggers` 中的额外项)启动一个新的会话 ID,并将消息的余部分继续传递`/new <model>` 接受模型别名、`provider/model` 或提供商名称(模糊匹配)来设置新会话模型。如果单独发送 `/new``/reset`OpenClaw 会运行一个简短的"问候"轮次来确认重置。
- 手动重置:从存储中删除特定键或除 JSONL 记录;下一条消息会重新创建它们。
- 隔离的定时任务每次运行都会创建一个新的 `sessionId`不复用空闲会话)。
- 重置策略:会话被重用直到过期,过期在下一条入站消息时评估。
- 每日重置:默认为 **Gateway 网关主机本地时间凌晨 4:00**。当会话的最后更新早于最近每日重置时间时,会话即为过期。
- 空闲重置(可选):`idleMinutes` 添加一个滑动空闲窗口。当同时配置每日和空闲重置时,**先过期者**强制新会话。
- 旧版仅空闲模式:如果设置了 `session.idleMinutes` 没有任何 `session.reset`/`resetByType` 配置,OpenClaw 会保持仅空闲模式以保持向后兼容。
- 按类型覆盖(可选):`resetByType` 允许你覆盖 `dm``group``thread` 会话策略(thread = Slack/Discord 线程、Telegram 话题、连接器提供的 Matrix 线程)。
- 按渠道覆盖(可选):`resetByChannel` 覆盖渠道的重置策略(适用于该渠道的所有会话类型,优先于 `reset`/`resetByType`)。
- 重置触发器:精确的 `/new``/reset`(加上 `resetTriggers` 中的任何额外项)启动新的会话 ID 并传递消息的余部分。`/new <model>` 接受模型别名、`provider/model` 或提供商名称(模糊匹配)来设置新会话模型。如果单独发送 `/new``/reset`OpenClaw 会运行一个简短的"问候"轮次来确认重置。
- 手动重置:从存储中删除特定键或除 JSONL 对话记录;下一条消息会重新创建它们。
- 隔离的定时任务总是每次运行生成新的 `sessionId`没有空闲重用)。
## 发送策略(可选)
无需列出单个 ID 即可按特定会话类型阻止投递
阻止特定会话类型的投递,无需列出单个 ID。
```json5
{
@@ -98,27 +98,27 @@ OpenClaw 默认在 LLM 调用之前从内存上下文中修剪**旧的工具结
}
```
运行时覆盖(仅所有者):
运行时覆盖(仅所有者):
- `/send on`允许此会话发送
- `/send off`禁止此会话发送
- `/send on`此会话允许
- `/send off`此会话拒绝
- `/send inherit` → 清除覆盖并使用配置规则
将这些作为独立消息发送以确保生效。
将这些作为独立消息发送以使其生效。
## 配置(可选重命名示例)
## 配置(可选重命名示例)
```json5
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // 保持群组键独立
dmScope: "main", // 私信连续性(共享收件箱请设置 per-channel-peer/per-account-channel-peer
scope: "per-sender", // keep group keys separate
dmScope: "main", // DM continuity (set per-channel-peer/per-account-channel-peer for shared inboxes)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// 默认值:mode=dailyatHour=4Gateway网关主机本地时间)。
// 如果同时设置了 idleMinutes,先到期的优先。
// Defaults: mode=daily, atHour=4 (gateway host local time).
// If you also set idleMinutes, whichever expires first wins.
mode: "daily",
atHour: 4,
idleMinutes: 120,
@@ -141,26 +141,26 @@ OpenClaw 默认在 LLM 调用之前从内存上下文中修剪**旧的工具结
## 检查
- `openclaw status` — 显示存储路径和最近的会话。
- `openclaw sessions --json`转储所有条目(使用 `--active <minutes>` 进行筛选)。
- `openclaw gateway call sessions.list --params '{}'` — 从运行中的 Gateway网关获取会话(使用 `--url`/`--token` 访问远程 Gateway网关)。
- 在聊天中发送 `/status` 作为独立消息可查看智能体是否可达、会话上下文使用了多少、当前的思考/详细模式开关,以及 WhatsApp 网页凭证的最后刷新时间(有助于发现需要重新链接的情况)。
- 发送 `/context list``/context detail` 查看系统提示和注入的工作区文件中的内容(以及最大的上下文贡献者)。
- 发送 `/stop` 作为独立消息可中止当前运行、清除该会话的排队后续消息,并停止由其生成的任何子智能体运行(回复包含已停止的数量)。
- 发送 `/compact`(可选指令)作为独立消息可总结旧上下文并释放窗口空间。参见 [/concepts/compaction](/concepts/compaction)。
- JSONL 记录可以直接打开以查看完整的对话轮次。
- `openclaw sessions --json`导出每个条目(使用 `--active <minutes>` 过滤)。
- `openclaw gateway call sessions.list --params '{}'` — 从运行中的 Gateway 网关获取会话(使用 `--url`/`--token` 进行远程 Gateway 网关访问)。
- 在聊天中单独发送 `/status` 消息可查看智能体是否可达、会话上下文使用了多少、当前的思考/详细模式开关,以及你的 WhatsApp Web 凭证上次刷新时间(有助于发现重新链接需求)。
- 发送 `/context list``/context detail` 查看系统提示中的内容和注入的工作区文件(以及最大的上下文贡献者)。
- 单独发送 `/stop` 消息可中止当前运行、清除该会话的排队后续操作,并停止从中生成的任何子智能体运行(回复包含已停止的数量)。
- 单独发送 `/compact`(可选指令)消息可总结旧上下文并释放窗口空间。参见 [/concepts/compaction](/concepts/compaction)。
- 可以直接打开 JSONL 对话记录查看完整轮次。
## 提示
- 将主键专用于一对一对话;让群组保各自独立的键。
- 自动清理时,删除单个键而不是整个存储,以保留其他地方的上下文。
- 将主键专用于 1:1 通信;让群组保各自的键。
- 自动清理时,删除单个键而不是整个存储,以保留其他地方的上下文。
## 会话来源元数据
每个会话条目在 `origin`记录其来源(尽力而为)
每个会话条目记录其来源(尽力而为)`origin` 中:
- `label`:人类可读标签(从对话标签 + 群组主题/频道解析)
- `provider`:规范化的渠道 ID(包括扩展)
- `from`/`to`:入站信封中的原始路由 ID
- `accountId`:提供商账 ID(多账时)
- `accountId`:提供商账 ID(多账时)
- `threadId`:渠道支持时的线程/话题 ID
来源字段为私信、频道和群组填充。如果连接器仅更新投递路由(例如,保持私信主会话活跃),它仍应提供入站上下文,以便会话保留其说明性元数据。扩展可以通过在入站上下文中发送 `ConversationLabel``GroupSubject``GroupChannel``GroupSpace``SenderName`并调用 `recordSessionMetaFromInbound`(或将相同上下文传递给 `updateLastRoute`)来实现。
来源字段为私信、频道和群组填充。如果连接器仅更新投递路由(例如,保持私信主会话新鲜),它仍应提供入站上下文,以便会话保留其解释器元数据。扩展可以通过在入站上下文中发送 `ConversationLabel``GroupSubject``GroupChannel``GroupSpace``SenderName` 并调用 `recordSessionMetaFromInbound`(或将相同上下文传递给 `updateLastRoute`)来实现。
+55 -55
View File
@@ -1,65 +1,65 @@
---
read_when:
- 解释流式传输或分块在渠道上的工作方式
- 更改块流式传输或渠道分块行为
- 调试重复/提前的块回复或草稿流式传输问题
- 解释流式传输或分块在渠道上如何工作
- 更改块流式传输或渠道分块行为
- 调试重复/提前的块回复或草稿流式传输
summary: 流式传输 + 分块行为(块回复、草稿流式传输、限制)
title: 流式传输分块
title: 流式传输分块
x-i18n:
generated_at: "2026-02-01T20:24:24Z"
generated_at: "2026-02-03T10:05:41Z"
model: claude-opus-4-5
provider: pi
source_hash: f014eb1898c4351b1d6b812223226d91324701e3e809cd0f3faf6679841bc353
source_path: concepts/streaming.md
workflow: 14
workflow: 15
---
# 流式传输 + 分块
OpenClaw 有两个独立的"流式传输"层:
- **块流式传输(渠道):** 在助手生成内容时发已完成的**块**。这些是普通的渠道消息(不是 token 增量)。
- **类 Token 流式传输(仅 Telegram):** 在生成过程中用部分文本更新**草稿气泡**;最终消息在结束时发送。
- **块流式传输(渠道):** 在助手写入时发已完成的**块**。这些是普通的渠道消息(不是令牌增量)。
- **类令牌流式传输(仅 Telegram):** 在生成用部分文本更新**草稿气泡**;最终消息在结束时发送。
目前**没有真正的 token 流式传输**到外部渠道消息。Telegram 草稿流式传输是唯一的部分流式传输界面。
目前**没有真正的令牌流式传输**到外部渠道消息。Telegram 草稿流式传输是唯一的部分流式传输界面。
## 块流式传输(渠道消息)
## 块流式传输(渠道消息)
块流式传输在助手输出可用时以粗粒度块发送。
块流式传输在助手输出可用时以粗粒度块发送。
```
Model output
模型输出
└─ text_delta/events
├─ (blockStreamingBreak=text_end)
│ └─ chunker emits blocks as buffer grows
│ └─ 分块器在缓冲区增长时发出块
└─ (blockStreamingBreak=message_end)
└─ chunker flushes at message_end
└─ channel send (block replies)
└─ 分块器在 message_end 时刷新
└─ 渠道发送(块回复)
```
图例:
- `text_delta/events`:模型流事件(对于非流式模型可能较为稀疏)。
- `chunker``EmbeddedBlockChunker`,应用最小/最大边界 + 断点偏好
- `text_delta/events`:模型流事件(对于非流式模型可能稀疏)。
- `chunker`应用最小/最大边界 + 断点偏好的 `EmbeddedBlockChunker`
- `channel send`:实际的出站消息(块回复)。
**控制项:**
- `agents.defaults.blockStreamingDefault``"on"`/`"off"`(默认关闭)。
- 渠道覆盖:`*.blockStreaming`(以及账户变体)可渠道强制 `"on"`/`"off"`
- 渠道覆盖:`*.blockStreaming`(以及账户变体)可为每个渠道强制设置 `"on"`/`"off"`
- `agents.defaults.blockStreamingBreak``"text_end"``"message_end"`
- `agents.defaults.blockStreamingChunk``{ minChars, maxChars, breakPreference? }`
- `agents.defaults.blockStreamingCoalesce``{ minChars?, maxChars?, idleMs? }`(发送前合并流式块)。
- 渠道硬上限:`*.textChunkLimit`(例如 `channels.whatsapp.textChunkLimit`)。
- 渠道分块模式:`*.chunkMode`(默认 `length``newline` 在空行(段落边界)分割,然后再按长度分块)。
- Discord 软上限:`channels.discord.maxLinesPerMessage`(默认 17拆分过长的回复以避免 UI 裁剪。
- 渠道硬上限:`*.textChunkLimit`(例如 `channels.whatsapp.textChunkLimit`)。
- 渠道分块模式:`*.chunkMode`(默认 `length``newline`长度分块之前按空行(段落边界)分割)。
- Discord 软上限:`channels.discord.maxLinesPerMessage`(默认 17分割高度较大的回复以避免 UI 裁剪。
**边界语义:**
- `text_end`:分块器发出块后立即流式传输;在每个 `text_end` 时刷新。
- `message_end`:等助手消息完成后,再刷新缓冲输出。
- `text_end`:分块器发出立即流式传输;在每个 `text_end` 时刷新。
- `message_end`:等助手消息完成,然后刷新缓冲输出。
`message_end`缓冲文本超过 `maxChars` 时仍会使用分块器,因此可能在最后发出多个块。
如果缓冲文本超过 `maxChars``message_end` 仍然使用分块器,因此可能在最后发出多个块。
## 分块算法(低/高边界)
@@ -68,66 +68,66 @@ Model output
- **低边界:** 在缓冲区 >= `minChars` 之前不发出(除非强制)。
- **高边界:** 优先在 `maxChars` 之前分割;如果强制,则在 `maxChars` 处分割。
- **断点偏好:** `paragraph``newline``sentence``whitespace` → 硬断点。
- **代码围栏:** 永远不在围栏内分割;当在 `maxChars`强制分割时,关闭重新打开围栏以保持 Markdown 有效。
- **代码围栏:** 不在围栏内分割;当在 `maxChars` 处强制分割时,关闭 + 重新打开围栏以保持 Markdown 有效。
`maxChars` 被限制在渠道 `textChunkLimit` 内,因此不会超过渠道的上限。
`maxChars` 被限制在渠道 `textChunkLimit` 内,因此你无法超过渠道的上限。
## 合并(合并流式块)
块流式传输启用时,OpenClaw 可以在发送前**合并连续的块**。这减少了"单行刷屏"的情况,同时仍提供渐进式输出。
启用分块流式传输时,OpenClaw 可以在发送前**合并连续的块分块**。这减少了"单行刷屏",同时仍提供渐进式输出。
- 合并会等待**空闲间**`idleMs`)后刷新。
- 缓冲区受 `maxChars` 限制,超出时会刷新。
- `minChars` 防止在积累足够文本之前发送微小片段(最终刷新始终发送剩余文本)。
- 连接符 `blockStreamingChunk.breakPreference` 派生(`paragraph``\n\n``newline``\n``sentence` → 空格)。
- 渠道覆盖通过 `*.blockStreamingCoalesce` 设置(包括账户配置)。
- 除非覆盖,Signal/Slack/Discord 的默认合并 `minChars` 会提升至 1500。
- 合并**空闲间**`idleMs`)后刷新。
- 缓冲区受 `maxChars` 限制,超过时将刷新。
- `minChars` 防止微小片段发送,直到累积足够文本(最终刷新始终发送剩余文本)。
- 连接符 `blockStreamingChunk.breakPreference` 派生(`paragraph``\n\n``newline``\n``sentence` → 空格)。
- 渠道覆盖通过 `*.blockStreamingCoalesce` 可用(包括账户配置)。
- 除非覆盖,Signal/Slack/Discord 的默认合并 `minChars` 提高到 1500。
## 块之间的仿真人节奏
## 块之间的人节奏
块流式传输启用时,你可以在块回复之间(第一个块之后)添加**随机停顿**。这多气泡回复感觉更自然。
启用分块流式传输时,你可以在块回复之间添加**随机暂停**(在第一个块之后)。这使多气泡响应感觉更自然。
- 配置:`agents.defaults.humanDelay`(通过 `agents.list[].humanDelay` 按智能体覆盖)。
- 模式:`off`(默认)、`natural`8002500ms)、`custom``minMs`/`maxMs`)。
- 仅适用于**块回复**,不适用于最终回复或工具摘要。
## "流式发送块还是一次性发送全部"
## "流式传输块或全部内容"
对应关系
这映射到
- **流式发送块:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"`(边生成边发)。非 Telegram 渠道还需要设置 `*.blockStreaming: true`
- **结束时一次性发送** `blockStreamingBreak: "message_end"`(刷新一次,如果内容很长可能产生多个块)。
- **不使用块流式传输:** `blockStreamingDefault: "off"`最终回复)。
- **流式传输块:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"`(边生成边发)。非 Telegram 渠道还需要 `*.blockStreaming: true`
- **最后流式传输全部内容** `blockStreamingBreak: "message_end"`(刷新一次,如果很长可能多个块)。
- **无分块流式传输:** `blockStreamingDefault: "off"`只有最终回复)。
**渠道说明:** 对于非 Telegram 渠道,块流式传输**默认关闭**,除非 `*.blockStreaming` 显式设置为 `true`。Telegram 可以通过 `channels.telegram.streamMode` 进行草稿流式传输,无需块回复
**渠道说明:** 对于非 Telegram 渠道,块流式传输**默认关闭**,除非 `*.blockStreaming` 明确设置为 `true`。Telegram 可以在没有块回复的情况下流式传输草稿(`channels.telegram.streamMode`
配置位置提醒:`blockStreaming*` 默认值位于 `agents.defaults` 下,而根配置。
配置位置提醒:`blockStreaming*` 默认值位于 `agents.defaults` 下,而不是根配置。
## Telegram 草稿流式传输(类 Token
## Telegram 草稿流式传输(类令牌
Telegram 是唯一支持草稿流式传输的渠道:
- 在**带题的私聊**中使用 Bot API `sendMessageDraft`
- 在**带题的私聊**中使用 Bot API `sendMessageDraft`
- `channels.telegram.streamMode: "partial" | "block" | "off"`
- `partial`:用最新的流式文本更新草稿。
- `block`:以分块方式更新草稿(使用相同的分块器规则)。
- `off`不进行草稿流式传输。
- `block`:以分块方式更新草稿(相同的分块器规则)。
- `off`草稿流式传输。
- 草稿分块配置(仅用于 `streamMode: "block"`):`channels.telegram.draftChunk`(默认值:`minChars: 200``maxChars: 800`)。
- 草稿流式传输与块流式传输是分离的;块回复默认关闭,仅在非 Telegram 渠道通过 `*.blockStreaming: true` 启用。
- 草稿流式传输与块流式传输分开;块回复默认关闭,仅在非 Telegram 渠道通过 `*.blockStreaming: true` 启用。
- 最终回复仍然是普通消息。
- `/reasoning stream` 将推理过程写入草稿气泡(仅 Telegram)。
- `/reasoning stream` 将推理写入草稿气泡(仅 Telegram)。
当草稿流式传输处于活跃状态时,OpenClaw 会禁用该回复块流式传输以避免双重流式传输。
当草稿流式传输活跃时,OpenClaw 会该回复禁用分块流式传输以避免双重流式传输。
```
Telegram (private + topics)
└─ sendMessageDraft (draft bubble)
├─ streamMode=partial → update latest text
└─ streamMode=block → chunker updates draft
└─ final reply → normal message
Telegram(私聊 + 主题)
└─ sendMessageDraft(草稿气泡)
├─ streamMode=partial → 更新最新文本
└─ streamMode=block → 分块器更新草稿
└─ 最终回复 → 普通消息
```
图例:
- `sendMessageDraft`:Telegram 草稿气泡(不是真正的消息)。
- `final reply`:普通 Telegram 消息发送。
- `final reply`:普通 Telegram 消息发送。
+35 -35
View File
@@ -2,56 +2,56 @@
read_when:
- 编辑系统提示词文本、工具列表或时间/心跳部分
- 更改工作区引导或 Skills 注入行为
summary: OpenClaw 系统提示词的内容及其组装方式
summary: OpenClaw 系统提示词包含的内容及其组装方式
title: 系统提示词
x-i18n:
generated_at: "2026-02-01T20:24:17Z"
generated_at: "2026-02-03T07:46:58Z"
model: claude-opus-4-5
provider: pi
source_hash: bef4b2674ba0414ce28fd08a4c3ead0e0ebe989e7df3c88ca8a0b2abfec2a50b
source_path: concepts/system-prompt.md
workflow: 14
workflow: 15
---
# 系统提示词
OpenClaw 为每次智能体运行构建自定义系统提示词。该提示词由 **OpenClaw **,不使用 p-coding-agent 默认提示词。
OpenClaw 为每次智能体运行构建自定义系统提示词。该提示词由 **OpenClaw **,不使用 p-coding-agent 默认提示词。
提示词由 OpenClaw 组装并注入到每次智能体运行中。
提示词由 OpenClaw 组装并注入到每次智能体运行中。
## 结构
提示词有意保持紧凑,使用固定部分:
提示词设计紧凑,使用固定部分:
- **工具**:当前工具列表简短描述。
- **安全**:简短的护提醒,避免模型追求权力或绕过监督。
- **Skills**(可用):告诉模型如何按需加载 Skills 指令。
- **OpenClaw 自更新**:如何运行 `config.apply``update.run`
- **工作区**:工作目录(`agents.defaults.workspace`)。
- **文档**:OpenClaw 文档的本地路径(仓库或 npm 包)及查阅时机
- **工作区文件(注入的)**:表明引导文件包含在下方
- **沙箱**(启用时):表沙箱隔离运行时、沙箱路径,以及是否可用提权执行。
- **当前日期和时间**:用户本地时间、时区和时间格式。
- **回复标签**:支持的提供商的可选回复标签语法。
- **心跳**:心跳提示和确认行为。
- **运行时**:主机、操作系统、Node、模型、仓库根目录(检测到时)、思考级别(一行)。
- **推理**:当前可见性级别 /reasoning 切换提示。
- **Tooling**:当前工具列表 + 简短描述。
- **Safety**:简短的护提醒,避免追求权力的行为或绕过监督。
- **Skills**如果可用):告诉模型如何按需加载 Skill 指令。
- **OpenClaw Self-Update**:如何运行 `config.apply``update.run`
- **Workspace**:工作目录(`agents.defaults.workspace`)。
- **Documentation**:OpenClaw 文档的本地路径(仓库或 npm 包)以及何时阅读它们
- **Workspace Files (injected)**:表示下方包含引导文件
- **Sandbox**(启用时):表沙箱隔离运行时、沙箱路径,以及是否可用提权执行。
- **Current Date & Time**:用户本地时间、时区和时间格式。
- **Reply Tags**:支持的提供商的可选回复标签语法。
- **Heartbeats**:心跳提示和确认行为。
- **Runtime**:主机、操作系统、node、模型、仓库根目录(检测到时)、思考级别(一行)。
- **Reasoning**:当前可见性级别 + /reasoning 切换提示。
系统提示词中的安全护是建议性的。它们导模型行为但不强制执行策略。使用工具策略、执行审批、沙箱隔离和渠道白名单进行硬性执行;操作人员可以按设计禁用这些功能
系统提示词中的安全护是建议性的。它们导模型行为但不强制执行策略。使用工具策略、执行审批、沙箱隔离和渠道允许列表进行硬性执行;运维人员可以按设计禁用这些。
## 提示词模式
OpenClaw 可以为子智能体渲染更小的系统提示词。运行时为每次运行设置一个 `promptMode`用户配置):
OpenClaw 可以为子智能体渲染更小的系统提示词。运行时为每次运行设置一个 `promptMode`不是面向用户配置):
- `full`(默认):包含上述所有部分。
- `minimal`:用于子智能体;省略**Skills**、**记忆召回**、**OpenClaw 自更新**、**模型别名**、**用户身份**、**回复标签**、**消息**、**静默回复**和**心跳**。工具、**安全**、工作区、沙箱、当前日期和时间(已知时)、运行时和注入的上下文仍然可用。
- `none`:仅返回基身份行。
- `minimal`:用于子智能体;省略 **Skills**、**Memory Recall**、**OpenClaw Self-Update**、**Model Aliases**、**User Identity**、**Reply Tags**、**Messaging**、**Silent Replies** 和 **Heartbeats**。Tooling、**Safety**、Workspace、Sandbox、Current Date & Time(已知时)、Runtime 和注入的上下文仍然可用。
- `none`:仅返回基身份行。
`promptMode=minimal` 时,额外注入的提示词标记为**子智能体上下文**而非**群聊上下文**。
`promptMode=minimal` 时,额外注入的提示词标记为 **Subagent Context** 而不是 **Group Chat Context**
## 工作区引导注入
引导文件经过裁剪后附加在**项目上下文**下,使模型无需显式读取即可看到身份和配置上下文:
引导文件被修剪后附加在 **Project Context** 下,这样模型无需显式读取即可看到身份和配置上下文:
- `AGENTS.md`
- `SOUL.md`
@@ -59,30 +59,30 @@ OpenClaw 可以为子智能体渲染更小的系统提示词。运行时为每
- `IDENTITY.md`
- `USER.md`
- `HEARTBEAT.md`
- `BOOTSTRAP.md`(仅在全新工作区
- `BOOTSTRAP.md`(仅在全新工作区
大文件会截断并附加标记。每个文件的最大大小由 `agents.defaults.bootstrapMaxChars` 控制(默认:20000)。缺失的文件会注入一个简短的缺失文件标记。
大文件会截断标记被截断。每个文件的最大大小由 `agents.defaults.bootstrapMaxChars` 控制(默认:20000)。缺失的文件会注入一个简短的缺失文件标记。
内部钩子可以通过 `agent:bootstrap` 拦截此步骤以修改或替换注入的引导文件(例如将 `SOUL.md` 替换为备选人格)。
内部钩子可以通过 `agent:bootstrap` 拦截此步骤以修改或替换注入的引导文件(例如将 `SOUL.md` 替换为其他角色)。
要查每个注入文件贡献(原始 vs 注入、截断情况,以及工具模式开销),使用 `/context list``/context detail`。参见[上下文](/concepts/context)。
查每个注入文件贡献了多少(原始 vs 注入、截断,加上工具 schema 开销),使用 `/context list``/context detail`。参见[上下文](/concepts/context)。
## 时间处理
当用户时区已知时,系统提示词包含专门的**当前日期和时间**部分。为保持提示词缓存稳定,现在包含**时区**不含动态时钟或时间格式)。
当用户时区已知时,系统提示词包含专用的 **Current Date & Time** 部分。为保持提示词缓存稳定,现在包含**时区**没有动态时钟或时间格式)。
当智能体需要当前时间时,请使用 `session_status`;状态卡片包含时间戳行。
当智能体需要当前时间时使用 `session_status`;状态卡片包含时间戳行。
配置方式:
- `agents.defaults.userTimezone`
- `agents.defaults.timeFormat``auto` | `12` | `24`
见[日期和时间](/date-time)了解全部行为细节
完整行为详情参见[日期和时间](/date-time)。
## Skills
当存在符合条件的 Skills 时,OpenClaw 注入一个紧凑的**可用 Skills 列表**`formatSkillsForPrompt`),其中包含每个 Skills 的**文件路径**。提示词指示模型使用 `read` 加载位于所列位置(工作区、托管或捆绑)的 SKILL.md。如果没有符合条件的 Skills,则省略 Skills 部分。
当存在符合条件的 Skills 时,OpenClaw 注入一个紧凑的**可用 Skills 列表**`formatSkillsForPrompt`),其中包含每个 Skill 的**文件路径**。提示词指示模型使用 `read` 加载列位置(工作区、托管或内置)的 SKILL.md。如果没有符合条件的 Skills,则省略 Skills 部分。
```
<available_skills>
@@ -94,8 +94,8 @@ OpenClaw 可以为子智能体渲染更小的系统提示词。运行时为每
</available_skills>
```
样可以保持基础提示词精简,同时仍然支持有针对性的 Skills 使用。
使基础提示词保持小巧,同时仍然支持有针对性的 Skill 使用。
## 文档
可用,系统提示词包含一个**文档**部分,指向本地 OpenClaw 文档目录(仓库工作区中的 `docs/`捆绑的 npm 包文档),并注明公共镜像、源代码仓库、社区 Discord 和 ClawHub (https://clawhub.com) 用于 Skills 发现。提示词指示模型在查询 OpenClaw 行为、命令、配置或架构时优先查阅本地文档,并可能时自行运行 `openclaw status`(仅在无法访问时询问用户)。
如果可用,系统提示词包含一个 **Documentation** 部分,指向本地 OpenClaw 文档目录(仓库工作区中的 `docs/`打包的 npm 包文档),并注明公共镜像、源仓库、社区 Discord 和 ClawHub (https://clawhub.com) 用于 Skills 发现。提示词指示模型首先查阅本地文档了解 OpenClaw 行为、命令、配置或架构,并可能自己运行 `openclaw status`(仅在无法访问时询问用户)。
+48 -48
View File
@@ -1,39 +1,39 @@
---
read_when:
- 更新协议模式或代码生成
summary: TypeBox 模式作为 Gateway网关协议的唯一事实来源
summary: TypeBox 模式作为 Gateway 网关协议的唯一事实来源
title: TypeBox
x-i18n:
generated_at: "2026-02-01T20:24:36Z"
generated_at: "2026-02-03T07:47:23Z"
model: claude-opus-4-5
provider: pi
source_hash: 233800f4f5fabe8ed0e1b3d8aded2eca27252e08c9b0b24ea9c6293e9282c918
source_path: concepts/typebox.md
workflow: 14
workflow: 15
---
# TypeBox 作为协议的唯一事实来源
# TypeBox 作为协议的事实来源
最后更新:2026-01-10
TypeBox 是一个 TypeScript 优先的模式库。我们用它来定义 **Gateway网关 WebSocket 协议**(握手、请求/响应、服务器事件)。这些模式驱动**运行时验证**、**JSON Schema 导出**以及 macOS 应用的 **Swift 代码生成**。一个事实来源;其他一切都是生成的。
TypeBox 是一个 TypeScript 优先的模式库。我们用它来定义 **Gateway 网关 WebSocket 协议**(握手、请求/响应、服务器事件)。这些模式驱动**运行时验证**、**JSON Schema 导出** macOS 应用的 **Swift 代码生成**。一个事实来源;其他一切都是生成的。
如果你想了解更高层次的协议上下文,请从 [Gateway网关架构](/concepts/architecture) 开始。
如果你想了解更高层次的协议上下文,请从 [Gateway 网关架构](/concepts/architecture)开始。
## 心智模型(30 秒)
Gateway网关 WS 消息都是以下三种帧之一:
Gateway 网关 WS 消息都是以下三种帧之一:
- **请求**`{ type: "req", id, method, params }`
- **响应**`{ type: "res", id, ok, payload | error }`
- **事件**`{ type: "event", event, payload, seq?, stateVersion? }`
- **Request**`{ type: "req", id, method, params }`
- **Response**`{ type: "res", id, ok, payload | error }`
- **Event**`{ type: "event", event, payload, seq?, stateVersion? }`
第一帧**必须**是 `connect` 请求。之后,客户端可以调用方法(如 `health``send``chat.send`)并订阅事件(如 `presence``tick``agent`)。
第一帧**必须**是 `connect` 请求。之后,客户端可以调用方法(`health``send``chat.send`)并订阅事件(`presence``tick``agent`)。
连接流程(最):
连接流程(最):
```
Client Gateway网关
Client Gateway
|---- req:connect -------->|
|<---- res:hello-ok --------|
|<---- event:tick ----------|
@@ -41,46 +41,46 @@ Client Gateway网关
|<---- res:health ----------|
```
方法 + 事件:
方法 + 事件:
| 类别 | 示例 | 备注 |
| ---- | --------------------------------------------------------- | ----------------------------------- |
| 核心 | `connect``health``status` | `connect` 必须在首位 |
| 消息 | `send``poll``agent``agent.wait` | 有副作用的操作需要 `idempotencyKey` |
| 聊天 | `chat.history``chat.send``chat.abort``chat.inject` | WebChat 使用这些 |
| 会话 | `sessions.list``sessions.patch``sessions.delete` | 会话管理 |
| 节点 | `node.list``node.invoke``node.pair.*` | Gateway网关 WS + 节点操作 |
| 事件 | `tick``presence``agent``chat``health``shutdown` | 服务器推送 |
| 类别 | 示例 | 说明 |
| ---- | --------------------------------------------------------- | ------------------------------- |
| 核心 | `connect``health``status` | `connect` 必须是第一个 |
| 消息 | `send``poll``agent``agent.wait` | 有副作用的需要 `idempotencyKey` |
| 聊天 | `chat.history``chat.send``chat.abort``chat.inject` | WebChat 使用这些 |
| 会话 | `sessions.list``sessions.patch``sessions.delete` | 会话管理 |
| 节点 | `node.list``node.invoke``node.pair.*` | Gateway 网关 WS + 节点操作 |
| 事件 | `tick``presence``agent``chat``health``shutdown` | 服务器推送 |
权威列表位于 `src/gateway/server.ts``METHODS``EVENTS`)。
权威列表 `src/gateway/server.ts``METHODS``EVENTS`
## 模式文件位置
## 模式所在位置
-文件`src/gateway/protocol/schema.ts`
-`src/gateway/protocol/schema.ts`
- 运行时验证器(AJV):`src/gateway/protocol/index.ts`
- 服务器握手 + 方法分发:`src/gateway/server.ts`
- 节点客户端:`src/gateway/client.ts`
- 生成的 JSON Schema`dist/protocol.schema.json`
- 生成的 Swift 模型:`apps/macos/Sources/OpenClawProtocol/Gateway网关Models.swift`
- 生成的 Swift 模型:`apps/macos/Sources/OpenClawProtocol/GatewayModels.swift`
## 当前流水线
## 当前流
- `pnpm protocol:gen`
- 将 JSON Schemadraft07)写入 `dist/protocol.schema.json`
- `pnpm protocol:gen:swift`
- 生成 Swift Gateway网关模型
- 生成 Swift Gateway 网关模型
- `pnpm protocol:check`
- 运行两个生成器并验证输出已提交
## 模式在运行时的使用方式
- **服务器端**:每个入站帧都通过 AJV 验证。握手仅接受参数匹配 `ConnectParams``connect` 请求。
- **客户端**:JS 客户端在使用事件和响应帧之前进行验证
- **方法接口**Gateway网关在 `hello-ok` 中公布支持的 `methods``events`
- **服务器端**:每个入站帧都 AJV 验证。握手仅接受参数匹配 `ConnectParams``connect` 请求。
- **客户端**JS 客户端在使用之前验证事件和响应帧。
- **方法表面**Gateway 网关在 `hello-ok` 中公布支持的 `methods``events`
## 示例帧
连接(第一条消息):
Connect(第一条消息):
```json
{
@@ -143,7 +143,7 @@ Hello-ok 响应:
## 最小客户端(Node.js
最小可用流程:连接 + 健康检查
最小可用流程:connect + health
```ts
import { WebSocket } from "ws";
@@ -183,7 +183,7 @@ ws.on("message", (data) => {
});
```
## 实示例:端到端添加一个方法
## 实示例:端到端添加方法
示例:添加一个新的 `system.echo` 请求,返回 `{ ok: true, text }`
@@ -217,7 +217,7 @@ export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;
2. **验证**
`src/gateway/protocol/index.ts` 中导出 AJV 验证器:
`src/gateway/protocol/index.ts`导出一个 AJV 验证器:
```ts
export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEchoParamsSchema);
@@ -225,10 +225,10 @@ export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEcho
3. **服务器行为**
`src/gateway/server-methods/system.ts` 中添加处理
`src/gateway/server-methods/system.ts` 中添加处理程序
```ts
export const systemHandlers: Gateway网关RequestHandlers = {
export const systemHandlers: GatewayRequestHandlers = {
"system.echo": ({ params, respond }) => {
const text = String(params.text ?? "");
respond(true, { ok: true, text });
@@ -236,7 +236,7 @@ export const systemHandlers: Gateway网关RequestHandlers = {
};
```
`src/gateway/server-methods.ts` 中注册(已合并 `systemHandlers`),然后将 `"system.echo"` 添加到 `src/gateway/server.ts``METHODS`
`src/gateway/server-methods.ts` 中注册(已合并 `systemHandlers`),然后将 `"system.echo"` 添加到 `src/gateway/server.ts` `METHODS`
4. **重新生成**
@@ -252,28 +252,28 @@ pnpm protocol:check
Swift 生成器输出:
- 包含 `req``res``event``unknown` case `Gateway网关Frame` 枚举
- 带有 `req``res``event``unknown` 情况`GatewayFrame` 枚举
- 强类型的 payload 结构体/枚举
- `ErrorCode` 值和 `GATEWAY_PROTOCOL_VERSION`
未知帧类型保留为原始 payload 以实现向兼容。
未知帧类型保留为原始 payload 以实现向兼容。
## 版本控制 + 兼容性
- `PROTOCOL_VERSION` 位于 `src/gateway/protocol/schema.ts`
- 客户端发送 `minProtocol` + `maxProtocol`;服务器拒绝不匹配的版本
- `PROTOCOL_VERSION` `src/gateway/protocol/schema.ts`
- 客户端发送 `minProtocol` + `maxProtocol`;服务器拒绝不匹配的。
- Swift 模型保留未知帧类型以避免破坏旧客户端。
## 模式规范和约定
## 模式模式和约定
- 大多数对象使用 `additionalProperties: false` 以实现严格的 payload。
- `NonEmptyString` 是 ID 和方法/事件名称的默认类型
- 顶层 `Gateway网关Frame``type` 上使用**鉴别器**。
- 有副作用的方法通常需要在参数中包含 `idempotencyKey`(示例:`send``poll``agent``chat.send`)。
- `NonEmptyString` 是 ID 和方法/事件名称的默认
- 顶层 `GatewayFrame``type` 上使用**鉴别器**。
- 有副作用的方法通常需要在 params 中包含 `idempotencyKey`(示例:`send``poll``agent``chat.send`)。
## 实时 Schema JSON
## 实时 schema JSON
生成的 JSON Schema 位于仓库的 `dist/protocol.schema.json`发布的原始文件通常可在以下位置获取:
生成的 JSON Schema 仓库的 `dist/protocol.schema.json`。发布的原始文件通常可在以下位置获取:
- https://raw.githubusercontent.com/openclaw/openclaw/main/dist/protocol.schema.json