9.3 身份系统

生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~450,000 tokens,输出 ~36,000 tokens(本章合计)


OpenClaw 的每个 Agent 不只是一个"无名的助手"——它可以有名字、有 emoji 标识、有自定义头像、有独特的回复风格。这套身份系统让用户能够赋予 Agent 个性化的形象,同时在多 Agent 场景中帮助区分不同 Agent 的消息。

身份系统由三层组成:配置层(identity.ts)、文件层(identity-file.ts)、和头像层(identity-avatar.ts)。

9.3.1 AI 助手身份(src/agents/identity.ts

IdentityConfig:身份配置类型

Agent 身份从 OpenClaw 配置文件中读取。每个 Agent 可以在 agents.[id].identity 下定义身份信息:

# openclaw.yaml 示例
agents:
  agents:
    - id: default
      identity:
        name: "Aria"
        emoji: "🦊"

identity.ts 提供了一组解析函数,从配置中提取身份信息:

// src/agents/identity.ts
const DEFAULT_ACK_REACTION = "👀";

export function resolveAgentIdentity(
  cfg: OpenClawConfig,
  agentId: string,
): IdentityConfig | undefined {
  return resolveAgentConfig(cfg, agentId)?.identity;
}

resolveAgentConfig 来自 agent-scope.ts,它通过 Agent ID 在配置的 agents 列表中查找对应条目,并返回标准化后的配置对象。

确认反应(Ack Reaction)

当用户发送消息时,OpenClaw 会先发送一个"确认"表情反应(类似于 iMessage 的"已读"),告知用户消息已收到。默认是 👀,但可以自定义:

这意味着如果 Agent 有自定义 emoji(如 🦊),确认反应就会变成那个 emoji 而不是默认的 👀。

消息前缀系统

在多 Agent 场景或群聊中,需要区分哪条消息来自哪个 Agent。OpenClaw 通过消息前缀实现:

消息前缀的解析有一套复杂的优先级逻辑:

衍生解释——allowFrom 与消息前缀的关系

在某些通道(如 Signal、Telegram)中,OpenClaw 使用专用的号码/bot 账号发送消息。如果配置了 allowFrom(即指定哪些号码的消息被视为来自 OpenClaw),通道本身已经能区分消息来源,因此不需要额外的 [名字] 前缀。

回复前缀(Response Prefix)

与消息前缀不同,回复前缀用于 Agent 在回复用户消息时的标识。它支持四级优先配置:

"auto" 是一个特殊值,表示"自动使用 Agent 身份名"。这样配置既简洁又灵活:

拟人化延迟(Human Delay)

身份系统还包含一个有趣的功能——拟人化延迟。它让 Agent 的回复不再"秒回",而是模拟人类的打字延迟:

配置示例:

9.3.2 身份文件(src/agents/identity-file.ts

除了配置文件之外,Agent 还可以通过工作区中的 IDENTITY.md 文件定义身份。这提供了一种更加用户友好的方式——用户直接编辑 Markdown 文件即可自定义 Agent 形象。

AgentIdentityFile 类型

IDENTITY.md 解析

parseIdentityMarkdown 从 Markdown 格式中提取键值对:

一个典型的 IDENTITY.md 文件:

占位符检测

初始模板中的占位符文本需要被识别并忽略,避免将"pick something you like"当作真实的身份值:

normalizeIdentityValue 会清理 Markdown 格式标记、括号、Unicode 短横线等,确保即使占位符文本被用户稍微修改格式后仍能被正确识别:

身份有效性检测

identityHasValues 检查解析结果是否包含至少一个有意义的值:

从工作区加载身份

注意这里使用了同步读取readFileSync)。这是一个有意的设计选择——身份加载发生在 Agent 启动的关键路径上,文件通常很小(<1KB),同步读取避免了异步流程的复杂性。

9.3.3 身份头像(src/agents/identity-avatar.ts

头像让 Agent 在消息通道(如 Telegram、Signal)中拥有可视化的"面孔"。identity-avatar.ts 负责解析和验证头像来源。

头像解析结果类型

这个联合类型涵盖了头像的四种可能状态,使用 TypeScript 的可辨识联合(Discriminated Union)模式。

衍生解释——可辨识联合(Discriminated Union)

可辨识联合是 TypeScript 中一种强大的类型模式。通过一个公共字段(这里是 kind)来区分不同的类型分支。编译器可以根据 kind 的值自动推断其他字段的类型,实现类型安全的模式匹配:

头像来源解析

头像值可能来自两个地方:配置文件或 IDENTITY.md 文件:

头像类型判断

本地头像路径解析与安全检查

对于本地文件路径,OpenClaw 执行严格的安全验证:

安全检查包括三个维度:

  1. 路径遍历防护:通过 isPathWithin 确保解析后的真实路径(经过 realpath 解析符号链接后)仍在工作区目录内。这防止了 ../../etc/passwd 之类的路径遍历攻击。

  2. 扩展名白名单:只允许常见的图片格式,阻止上传可执行文件或其他危险格式。

  3. 文件存在性:确保引用的文件确实存在。

完整的头像解析流程

resolveAgentAvatar 将所有步骤串联起来:

决策树:

9.3.4 通道前缀身份

在多通道场景中,不同的消息通道可能需要不同的身份表现。OpenClaw 通过 resolveEffectiveMessagesConfig 统一处理消息前缀和回复前缀:

四级前缀优先级

回复前缀的配置支持四个层级(从高到低):

配置示例:

当值为 "auto" 时,系统自动使用 resolveIdentityNamePrefix 生成 [Name] 格式的前缀。这让配置既简洁又灵活——用户只需在 Agent 身份中设置一次 name,所有通道都可以通过 "auto" 引用。

身份信息在通道中的使用

当 OpenClaw 通过 Telegram、Signal 等通道发送消息时,身份系统的各个组件会协同工作:


本节小结

  1. 身份系统分为三层:配置层(identity.ts)处理优先级解析,文件层(identity-file.ts)解析 IDENTITY.md Markdown,头像层(identity-avatar.ts)处理多种头像来源。

  2. 消息前缀支持四级配置优先级(账号 > 通道 > 全局),"auto" 值自动引用 Agent 身份名,实现一处定义、多处引用。

  3. 头像安全验证包含路径遍历防护、扩展名白名单和文件存在性检查三重保障。

  4. 占位符检测通过标准化文本比较,确保模板中的引导性文本不会被误认为有效身份值。

  5. 拟人化延迟让 Agent 的回复行为更接近真人,可按 Agent 和全局两级配置。

  6. 整个身份系统的设计理念是配置优先、文件回退——配置文件中的设置始终覆盖 IDENTITY.md 文件中的设置。

Last updated