Skip to content

角色、Bot 与房间 ​

**角色(persona)**是一个跨会话保留记忆的身份,并有一个随时可以回去的固定地址;它的 profile 负责工具、权限、模型和执行方式。角色回答「它是谁、记得什么」,profile 回答「它能调用什么、怎么运行」,换掉 profile 绑定不会丢掉身份。Bot 是角色背后的常驻对话,定时提示词、另一个角色或房间都通过它找到这个角色;房间让多个角色在各自独立的成员会话里讨论同一主题。

从角色开始 ​

在「角色」页创建角色,或把角色卡放到 $KIKI_HOME/personas/release-guide/persona.md($KIKI_HOME 默认为 ~/.kiki):

yaml
---
name: 发布向导
title: 发布协调人
job: 检查发布准备情况
profile: agent
greeting: 这次准备发布什么?
memory:
  shared: [global, workspace]
---
你负责协调发布准备工作。主动询问缺失的证据,区分已确认事实与待解决问题。

目录名就是稳定 ID:使用小写字母、数字,以单个连字符分隔单词。Markdown 正文定义身份。可选的 model_alias 和 thinking_effort 指定已配置模型及思考档位,但不授予权限;tools 等字段会被拒绝,因为权限属于 profile。

在 GUI 新建会话时选择角色,或从终端启动:

sh
kiki --persona release-guide

每个角色都有一段固定的日常对话,侧栏那一行、切换器、会话顶栏和角色页打开的都是它,所以「找这个角色」每次都是同一段对话。一个角色可以同时持有多段,在它的对话列表里切换即可。终端里用 /persona switch release-guide 会打开新会话,旧会话保持原样;/persona list 列出全部角色。

显式选择的模型优先于角色模型;否则先看角色模型,再看 profile 或默认模型。显式选择其他 profile 会替换角色预设的 profile,但不会丢掉角色身份。

每个会话都会冻结自己的角色快照,编辑角色卡不会影响进行中的会话——新建会话或重建上下文后才会生效。开场白在你明确回复之前只是本地展示,打开会话不会把它写进模型历史。

记忆与角色卡 ​

角色记忆跟随角色,不随 profile 或模型切换而丢失。角色专属条目与其他角色隔离,默认也能读取公共 global 和 workspace 记忆,设置 memory.shared: [] 可排除。记忆页提供角色范围;模型、审批收件箱和可撤销的改动历史见记忆。删除角色会一并删除其记忆,清理失败时删除操作会报错并保留角色卡,方便重试。

角色页支持 Character Card V3 的 JSON、PNG、CHARX 导入导出,保存前先看导入预览:lorebook 条目会转成角色记忆并影响后续模型请求。未知扩展字段在导出时保留,但头像之外的二进制素材无法完整保留,这类卡片请留好原件。头像选择器接受不超过 20 MB 的 PNG、JPEG、WebP,裁剪后上传 256 像素的圆形或方形图,重载后保留。移除头像只恢复首字母,不删除角色或记忆。直接调 API 上传仍限制 2 MiB。复制创建新身份,不带会话状态和私有记忆;归档把角色从常规选择列表隐藏,但保留数据。

保存后的 persona.md 上限 1 MiB,示例和扩展各 256 KiB,按 UTF-8 字节计算。超限内容会在改动角色卡和记忆之前失败,缩短后重试即可。旧版无效或超限的角色卡仍可用 PUT /api/personas/{id} 替换,或用 DELETE /api/personas/{id} 删除,后者会先清理该角色的记忆。

常驻对话 ​

角色无论你有没有跟它说过话,都有一个稳定的地址。它的日常对话就是这个地址:侧栏那一行、切换器、会话顶栏和角色页打开的都是同一个;角色页还会列出该角色的其它对话,你可以把日常入口换成其中另一段。第一次打开时会创建它。

定时提示词、来自另一个角色的消息、房间里的席位访问的都是这同一个对话,不需要另外配置角色。它有独立的工作目录,默认 $KIKI_HOME/bots/<id>,也可以由角色卡用 home_workspace 指定。相关限制在 config.toml 里配置:

toml
[bot]
enabled = true
max_handoffs_per_hour = 30
room_budget = 12

会话的 delivery 为 reply 或 message。角色没有写 delivery 时,新建会话使用消息模式;会话的显式选择优先,已有会话保持保存的选择。没有角色的会话,以及明确选择 reply 的角色,仍直接回复。角色编辑器会保存界面显示的投递模式,包括显式选择的 reply。

在消息视图中,正常完成的轮次如果没有调用原生 SendMessage 工具,也会显示该轮末条完整普通回复。只要调用过它,即使发送失败、取消或待确认,也不会显示这条兜底回复。调用通过 messages 批量发送时,每条消息会在独立行中流式增长,并各自保留投递结果。长回复和已发送消息会自动续读全文。失败轮次保留失败标识。未作为消息显示的普通正文,包括未完成的回复,可切到过程视图读取。这种显示兜底不会向房间、其他角色或 IM 信道发送消息;这些目标仍需实际投递。

SendMessage 确认已投递给用户后,返回结果会提醒模型:请求已经完成且没有剩余工作时,直接结束轮次,不再补发收尾消息。进度消息不会阻止后续工具调用或待执行工作。原生执行器的消息轮次如果改以普通文本结束、且该工具可用,下一次模型请求会提醒模型用它发送之后的新回复,不会为已完成轮次追加请求或重发旧答案。

内置 agent profile 在消息模式中暴露 SendMessage,在 reply 轮次中不暴露。自定义 profile 如果显式设置了 tools 白名单,必须加入该工具;delivery 模式不会绕过 profile 权限。工具表在轮次内冻结,因此切换 delivery 会在下一轮生效。

SendMessage 可以发给用户,也可以用 to: "@名字" 发给另一个角色。同名时使用角色 ID。交接可以唤醒已关闭的常驻对话,并计入每小时上限;相同投递键的重试不会再占一个名额。附件是从会话工作区、附加目录或角色自己的区域复制的不可变副本,不能任意读取文件系统路径。附件的 kind 可指定 image、audio、voice 或 video 投递意图;省略时仍按普通 file 投递。只发附件时可以不带正文:

json
{
  "attachments": [
    { "path": "output/voice.ogg", "kind": "voice", "mime_type": "audio/ogg" }
  ]
}

连接会话信道 ​

发给用户的 SendMessage 会使用名为 internal 的 Kiki 内部信道,以及该会话已启用的 IM 绑定。新增 IM 绑定不会关闭内部信道。HTTP 客户端可用 rest.imSessions.channelViews(sessionId) 查看信道。

每个附件至少要有一个已启用信道支持,否则发送会报 media_unsupported;没有任何启用目标时会报 no_destination。只有部分信道支持某个附件时,Kiki 会向支持端发送,并在其它端提醒跳过了哪些媒体。收据的 channels 逐端返回 delivered、unsupported、failed 或 unknown;已投递的信道也可能在 unsupported 中列出跳过的类型。unknown 表示无法确认结果,平台可能已经接收,不要自动重发。

voice 是明确的语音意图,不会静默降为文件。内部信道用音频播放器播放 audio 和 voice。Discord、Slack、Matrix 支持普通 audio,但不支持发送平台原生 voice:Discord 和 Slack 把音频作为附件上传,Matrix 使用 m.audio。Matrix 仅支持未加密房间,向加密房间发送明文会被拒绝。

HTTP 客户端通过 rest.imSessions.setupCatalog() 和 setup(...) 配置这些连接。目录会返回各平台必填字段及实际能力:

平台必填字段配置方式
Discordbot_tokendiscord_install 根据 application_id 生成 Bot 邀请链接;还须在开发者后台启用 Message Content Intent。
Slackbot_token、app_tokenslack_manifest 创建 Socket Mode 应用;OAuth 可取得 Bot token,仍需单独提供应用级 xapp token。
Matrixhomeserver、access_tokenmatrix_discover 查询登录方式;可用 matrix_sso_begin / matrix_sso_complete 或 matrix_password 取得并保存 token。

调用 setup({ action: "save", provider_kind, fields }) 保存凭据时不会启动监听。接着用返回的 provider_instance_id 调用 check 和 listen(id, true),在平台给 Bot 发一条消息,再把出现的发现项确认绑定到目标会话或角色。已有 Telegram、飞书、OneBot 和微信连接保留原配置与绑定流程。连接认证见 REST API 指南;上述操作的 HTTP 入口是 GET / POST /api/im/sessions/setup 和 GET /api/im/sessions/targets/{sessionId}/channels。

确认绑定后,调用 rest.imSessions.testBinding(bindingId),会向该绑定的聊天发送一条明确标注测试的固定消息,不会启动模型回复。测试使用现有连接,要求绑定已启用且连接可用。对应 HTTP 请求是 POST /api/im/sessions/bindings/{bindingId}/test,正文为 {},不接受自定义正文或目标。结果包含 binding_id、status、message_ids 和可选的 detail。delivered 表示平台已接收,不代表对方已读;failed 时按返回原因修复后再试。unknown 时先查看聊天,再决定是否手动重试。

在房间中讨论 ​

创建房间时选择两到六个成员、归类工作区和主持人。角色成员获得独立的消息模式会话;API 也接受现有线程(kind: "thread"),沿用其原会话、工作区和权限,该线程须已准入线程通信,且不能是 subagent。出厂设置允许使用线程通信,并默认关闭。把该线程的会话打开,或把默认打开,它才能加入。用户把 [thread_communication] enabled 写成 false 是完全关闭;会话已关闭时,该线程的 Profile 不能把它打开。GUI 里可以在侧栏按住 Ctrl/⌘ 多选线程后选「拉进新房间」,在线程菜单用「加入房间…」,在房间「添加成员」的「线程」页签里加入,或在线程链接上选「和这些线程开房间」。谁会被唤醒由三条规则决定:

  1. 用户 @ 谁就唤醒谁;@everyone 或 @所有人 选择全部成员。
  2. 用户没有 @ 任何人时交给主持人,主持人不论是角色还是线程。
  3. 角色或线程的房间消息只唤醒它 @ 到的成员。没有 @ 的发言会记入房间,但不会唤醒任何人。

角色成员依次运行,已有线程则各有自己的队列。静音成员不会被 Agent 提及和主持兜底唤醒,但用户显式 @ 它时仍会唤醒。成员收到自上次成功完成汇总以来的消息,不含自己已记录的发言。成功批次已经覆盖的通知不会再单独开启轮次;失败或取消的轮次不会确认该批消息已处理。

预算限制每条用户消息之后的成员发言数,默认 12 条。用尽后讨论暂停,「继续」重置预算并恢复保留的任务。「暂停」取消排队唤醒但让当前轮次跑完;「停止所有」还会中断角色成员的活动轮次,但不会中断原线程任务,也不回滚已完成的动作。纯角色房间保留用户插话,混合房间保留排队任务。同一时刻只展示一张问题卡,后续排队。

线程成员默认 queueWhenBusy: true:房间输入等当前轮次结束,不会 steer。冷线程在自己的工作区恢复;没有选中某成员的消息会在该成员下次唤醒时汇总,不单独产生模型调用。线程必须用 ThreadSend({room, content, mentions?}) 发言,普通 Assistant 文本不会进入房间。mentions 使用准确的成员 ID(线程用 sessionId,角色用 personaId),不用显示名。不带 mentions 的发送不会唤醒主持人;主持人兜底只适用于用户消息。

改名、换主持人、静音和更换归类工作区都不会重写成员的系统提示词或权限。移除线程会在其会话留下系统记录、保留房间日志,不归档原线程。创建时要求两到六个成员,离开后可以少于两个。

成员无法唤醒时,房间会显示失败原因和恢复办法。模型未登录时,到「设置 → 模型与提供商 → 服务与账号」登录,或打开该成员的会话选择一个可用模型——已有成员会话保留绑定的模型,改角色卡不会改变它。修好后再发一条房间消息,失败成员不是主持人时请 @ 它。「继续」恢复的是暂停的房间,不会重试尚未暂停的失败唤醒。

API 入口 ​

SDK 提供 global.personas、global.bots、global.rooms;HTTP 客户端还提供 rest.personas、rest.bots、rest.rooms。列表直接返回数组。创建会话接受 persona 和 delivery;读取会话会返回 agent_config.persona = { id, name, avatarUrl? } 以及 delivery。

REST 资源位于 /api/personas、/api/bots、/api/rooms。房间成员、静音、主持人和预算通过 PATCH /api/rooms/{id} 更新;暂停、继续和停止分别使用对应的 POST 动作。GET /api/rooms/{id}/log 接受 afterId 和 limit。角色记忆入口为 /api/memory/persona?persona_id=<id> 或 /api/memory/persona_workspace?persona_id=<id>&workspace_id=<workspace>。

认证与连接方式见 REST API 指南。

下一步 ​