群组 — RPC Manual
权限层级
| 角色 | 说明 |
|---|---|
owner | 群主,最高权限,可转让 |
admin | 管理员,可管理成员和群设置 |
member | 普通成员,可收发消息 |
observer | 只读成员,仅可接收消息(预留,当前未实现) |
方法索引
群组生命周期
| 方法 | 说明 |
|---|---|
| group.create | 创建群组 |
| group.bind_aid | 为普通群绑定命名 AID |
| group.get_info | 查询群组信息(平铺格式,唯一推荐入口) |
| group.update | 更新群组资料 |
| group.list_my | 列出我的群组 |
| group.search | 搜索公开群 |
| group.suspend | 暂停群组 |
| group.resume | 恢复群组 |
| group.dissolve | 解散群组 |
成员管理
| 方法 | 说明 |
|---|---|
| group.add_member | 添加成员 |
| group.get_members | 获取成员列表 |
| group.kick | 踢出成员 |
| group.leave | 主动退群 |
| group.set_role | 设置角色 |
| group.transfer_owner | 转让群主 |
| group.bind_group_aid | 为匿名群绑定群身份 |
| group.renew_group_aid | 轮换群身份密钥 |
| group.ban | 封禁成员 |
| group.unban | 解封成员 |
| group.get_banlist | 获取封禁列表 |
入群流程
设置与分发
| 方法 | 说明 |
|---|---|
| group.set_settings | 统一设置群参数,含 dispatch_mode |
| group.get_settings | 统一读取群参数 |
消息
| 方法 | 说明 |
|---|---|
| group.send | 发送群消息 |
| group.recall | 撤回群消息 |
| group.thought.put | 写入某个群上下文的思考内容 |
| group.thought.get | 获取某个群上下文的思考内容 |
| group.pull | 增量拉取消息 |
| group.pull_events | 增量拉取事件 |
| group.ack | 确认已读(旧接口,等同 ack_messages) |
| group.ack_messages | 确认消息游标 |
| group.ack_events | 确认事件游标 |
多设备管理
| 方法 | 说明 |
|---|---|
| group.list_devices | 列出设备列表 |
| group.unregister_device | 注销设备 |
管理员与成员类型
| 方法 | 说明 |
|---|---|
| group.get_admins | 获取管理员列表 |
| group.get_master | 获取群主信息 |
| group.refresh_member_types | 刷新成员类型统计 |
统计与指标
| 方法 | 说明 |
|---|---|
| group.get_summary | 获取群组摘要 |
群设置
| 方法 | 说明 |
|---|---|
| group.set_settings | 统一设置群参数(含公告、规则、入群要求、dispatch_mode 等) |
| group.get_settings | 统一读取群参数 |
便利方法:SDK 提供向后兼容的便利方法(getAnnouncement/updateAnnouncement/getRules/updateRules/getJoinRequirements/updateJoinRequirements),并提供通用文档型方法(getSettingWithIndex/updateSettingWithIndex,Python 为 get_setting_with_index/update_setting_with_index,Go 为 GetSettingWithIndex/UpdateSettingWithIndex)。读取方法优先返回 SDK 本地缓存,本地没有对应值时才调用 get_settings 初始化;即使观察到远端 etag 不一致也不会自动 pull 远端。indexed 写入方法内部调用 updateGroupIndex 生成签名 group.index 并通过 set_settings CAS 提交。
群文件系统
| 方法 | 说明 |
|---|---|
| group.fs.ls | 列出目录 |
| group.fs.find | 查找节点 |
| group.fs.stat | 查看节点 |
| group.fs.lstat | 查看链接本身 |
| group.fs.df | 查看用量 |
| group.fs.create_download_ticket | 创建下载票据 |
| group.fs.set_acl | 授予群自有区角色写 ACL |
| group.fs.remove_acl | 撤销群自有区角色写 ACL |
| group.fs.get_acl | 查询群自有区角色 ACL |
| group.fs.list_acl | 查询群自有区角色 ACL(别名) |
| group.fs.mkdir | 创建目录 |
| group.fs.rm | 删除节点 |
| group.fs.cp | 远程复制 |
| group.fs.mv | 远程移动 |
| group.fs.check_upload | 上传前检查 |
| group.fs.create_upload_session | 创建上传会话 |
| group.fs.complete_upload | 完成上传 |
| group.fs.mount | 挂载成员数据区 |
| group.fs.umount | 卸载成员数据区 |
在线状态
| 方法 | 说明 |
|---|---|
| group.get_online_members | 在线成员 |
Group AID / Group ID 兼容规范
目标态群组主标识是 group_aid,canonical 形式为 {base}.{issuer-domain},例如 10042.agentid.pub、team01.agentid.pub、g-abc123.agentid.pub。新建群以 group_aid 为准;新群的兼容 group_id 列值也使用同一个 group_aid 字符串。历史 group_id 字段名和 RPC 参数名继续保留,但语义上只是兼容字段。
SDK 发起 group.* 调用时会把传入的 group_id / groupId / group_aid / groupAid 统一规范化为 group_aid。裸客户端也应使用同一 group_aid 生成签名材料和 E2EE AAD,避免同一群的历史别名产生不同材料。服务端响应可能同时返回 group_id 和 group_aid;新代码应优先读取 group_aid,仅兼容旧版本或历史数据时回退读取 group_id。
兼容输入包括目标态 {base}.{issuer-domain}、本域简写 {base} / g-{slug},以及旧格式 group.{issuer-domain}/{base}、{base}@issuer-domain、g-{slug}@issuer-domain、g-{slug}.{issuer-domain}。带域的旧输入会转换为 {base}.{issuer-domain};本域简写会在服务端或 SDK 有本域 issuer 配置时补成本域 group_aid。base 支持 5 位及以上小写字母或数字,或 4 到 64 位 [a-z0-9_-] 风格名称;旧 g- 前缀形式继续兼容,g- 后为 4 到 32 位小写字母或数字。命名群使用 group_name 作为 base,规则见 group.create 参数说明。
group.create 的新建语义以 group_aid 为准:命名群由 group_name + issuer 生成 group_aid,自动群由服务端群号生成 {number}.{issuer}。group_id 参数只作为旧客户端兼容别名;传入时不能是纯数字(纯数字群号保留给服务端自动分配),且规范化后的 group_aid 未被占用。如果已被占用或与历史别名碰撞会返回错误。
在 https://group.issuer-domain/... 这类群链接中,path 使用单段 group_aid,例如 https://group.agentid.pub/10042.agentid.pub/invite/ic-xxx、https://group.agentid.pub/g-abc123.agentid.pub/invite/ic-xxx。历史 base 简写链接可继续由服务端兼容解析。
群组生命周期
group.create
创建群组。调用者自动成为 owner。支持创建命名群(传入 group_name + public_key)。新建群主标识以 group_aid 为准;group_id 仅作为兼容字段保留。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 群组显示名称 |
group_aid | string | 否 | 目标态群 AID;新代码优先使用。传入时会规范化为 {base}.{issuer-domain},不能是纯数字 |
group_id | string | 否 | 兼容旧客户端的别名;值语义同 group_aid,不再推荐新代码使用 |
group_name | string | 否 | 命名群标识,4-64 字符,[a-z0-9_-]+,不以 guest/g- 开头。与 public_key 同时提供时创建命名群,并生成 {group_name}.{issuer-domain} |
public_key | string | 否 | 命名群公钥(base64 编码),与 group_name 同时提供 |
curve | string | 否 | 密钥曲线,默认 "P-256" |
visibility | string | 否 | "public" / "private",默认由配置决定 |
description | string | 否 | 群组描述 |
metadata | object | 否 | 自定义元数据 |
avatar_ref | string | 否 | 头像存储引用 |
join_mode | string | 否 | "open" / "approval" / "invite_only" / "closed",回退到 visibility 映射 |
join_question | string | 否 | 入群问题 |
auto_approve_patterns | array | 否 | 自动批准正则列表 |
max_pending | integer | 否 | 最大待审批数,默认 100 |
响应:
{
"group": {
"group_id": "my-team.agentid.pub",
"group_aid": "my-team.agentid.pub",
"name": "测试群",
"owner_aid": "alice.agentid.pub",
"creator_aid": "alice.agentid.pub",
"visibility": "private",
"status": "active",
"description": "",
"metadata": {},
"member_count": 1,
"message_seq": 0,
"event_seq": 0,
"group_url": "https://group.agentid.pub/my-team.agentid.pub",
"created_at": 1234567890000,
"updated_at": 1234567890000
},
"aid_cert": {
"cert": "-----BEGIN CERTIFICATE-----...",
"ca_cert": "-----BEGIN CERTIFICATE-----...",
"ca_chain": [],
"cert_sn": "abc123",
"curve": "P-256"
}
}
aid_cert仅在命名群创建时返回。group_aid是新代码应使用的主标识;group_id为兼容字段,新群通常与group_aid相同,历史群可能保留旧存储值。
标识格式:目标态为 {base}.{issuer-domain}。旧格式 group.{issuer-domain}/{base}、{base}@{issuer-domain} 会在 API 边界转换为目标态 group_aid。
group.bind_aid
为已有普通群绑定命名 AID(升级为命名群)。仅群主可操作。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容参数名,值使用目标态 group_aid |
group_name | string | 是 | 命名群标识,4-64 字符,[a-z0-9_-]+ |
public_key | string | 是 | 群公钥(base64 编码) |
curve | string | 否 | 密钥曲线,默认 "P-256" |
响应:
{
"group": { "group_id": "...", "group_aid": "my-team.agentid.pub", ... },
"aid_cert": { "cert": "...", "ca_cert": "...", "ca_chain": [], "cert_sn": "...", "curve": "P-256" }
}group.get_info
查询群组信息,返回平铺格式。默认返回公开字段;需要成员或管理员权限的字段必须通过 required 显式声明。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容参数名,值使用目标态 group_aid |
required | string[] | 否 | 受限字段声明:member、state、e2ee、avatar |
默认响应:
{
"found": true,
"group_id": "g-abc123.agentid.pub",
"group_aid": "g-abc123.agentid.pub",
"name": "开发讨论组",
"visibility": "public",
"status": "active",
"description": "技术讨论群",
"member_count": 42,
"created_at": 1234567890000
}required=["member"] 会额外返回 owner_aid、creator_aid、message_seq、event_seq、e2ee_epoch、updated_at、my_role 等成员可见字段。
group.get和group.info已合并到group.get_info;group.get_info默认行为等价于原公开信息查询。
group.update
更新群组资料。需要 admin 及以上权限。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容参数名,值使用目标态 group_aid |
name | string | 否 | 新名称 |
visibility | string | 否 | 新可见性 |
description | string | 否 | 新描述 |
metadata | object | 否 | 新元数据 |
avatar_ref | string | 否 | 新头像存储引用 |
group.list_my
列出当前用户加入的群组。group.list 是此方法的别名,两者等价。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
size | integer | 否 | 50 | 返回数量上限(最大 200,受 max_limit 配置限制) |
也接受
limit作为size的别名。
响应:
{
"items": [
{
"group_id": "g-abc123.agentid.pub",
"name": "项目讨论",
"visibility": "private",
"member_count": 5,
"updated_at": 1234567890000,
"role": "owner"
}
],
"total": 1,
"page": 1,
"size": 200,
"aid": "alice.agentid.pub"
}注意:当前
page固定为 1,不支持翻页。
group.search
搜索公开群组。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query | string | 否 | 搜索关键词(也接受 q) |
size | integer | 否 | 返回数量上限(也接受 limit) |
响应:
{
"query": "项目",
"page": 1,
"size": 50,
"items": [ ... ],
"total": 3
}注意:当前
page固定为 1,不支持翻页。仅返回公开群组。
group.suspend
暂停群组。暂停期间不能发送消息。需要 admin 及以上权限。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group": { ... },
"status": "suspended"
}若群组已处于暂停状态,
status为"unchanged"。
group.resume
恢复暂停的群组。需要 admin 及以上权限。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group": { ... },
"status": "active"
}若群组已处于活跃状态,
status为"unchanged"。
group.dissolve
永久解散群组。不可恢复。需要 owner 权限。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group_id": "g-abc123.agentid.pub",
"status": "dissolved"
}成员管理
group.add_member
添加成员。需要 admin 及以上权限。若设置 role=admin,需要 owner 权限。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
aid | string | 是 | 要添加的 AID |
role | string | 否 | "admin" / "member",默认 "member" |
member_type | string | 否 | "human" / "ai",默认 "human" |
响应:
{
"group": { ... },
"member": {
"aid": "bob.agentid.pub",
"role": "member",
"member_type": "human",
"joined_at": 1234567890000
}
}group.get_members
获取成员列表。支持分页和角色过滤。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
group_id | string | 是 | — | 群组标识;兼容字段,值语义为目标态 group_aid |
page | integer | 否 | 1 | 页码 |
size | integer | 否 | 50 | 每页条数(最大 200) |
role | string | 否 | — | 按角色过滤(owner/admin/member) |
响应:
{
"group_id": "g-abc123.agentid.pub",
"members": [
{
"group_id": "g-abc123.agentid.pub",
"aid": "alice.agentid.pub",
"role": "owner",
"member_type": "human",
"joined_at": 1234567890000,
"last_ack_seq": 100,
"last_pull_at": 1234567890000
}
],
"total": 1,
"count": 1,
"page": 1,
"size": 50
}group.kick
踢出成员。需要 admin 及以上权限,不能踢 owner。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
aid | string | 是 | 要踢出的 AID |
响应:
{
"group": { ... },
"removed_aid": "bob.agentid.pub"
}group.leave
主动退出群组。owner 不能直接退群,需先转让群主。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group": { ... },
"left_aid": "bob.agentid.pub"
}group.set_role
设置成员角色。owner 可将普通成员设为 admin,也可将 admin 设回 member;admin 不能修改其它成员角色,只能将自己的角色降为 member。不能通过 group.set_role 改变 owner 角色;群主只在建群或 group.transfer_owner 中变更。该 RPC 改变 membership 中的角色事实;owner/admin 默认拥有群自有区写权限,member 默认没有写权限。成员级群协作目录应通过 group.fs.set_acl 显式授予 role:member 的 rw 权限。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
aid | string | 是 | 目标 AID |
role | string | 是 | "admin" / "member" |
响应:
{
"group": { ... },
"member": {
"group_id": "g-abc123.agentid.pub",
"aid": "bob.agentid.pub",
"role": "admin",
"member_type": "human",
"joined_at": 1234567890000,
"last_ack_seq": 0,
"last_pull_at": 0
},
"old_role": "member",
"new_role": "admin",
"acl_model": "role_based",
"acl_policy": "unchanged"
}group.transfer_owner
转让群主。需要 owner 权限。原 owner 转为 admin。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
new_owner | string | 是 | 新群主 AID(也接受 aid) |
响应:
{
"group": { ... },
"old_owner": "alice.agentid.pub",
"new_owner": "bob.agentid.pub"
}group.bind_group_aid
为匿名群绑定群身份(group_aid)。需要 owner 权限。
幂等保证:
- 已绑定且公钥匹配:返回已绑定的 group_aid 和证书
- 已绑定但公钥不同:报错
group_aid_already_bound_different_key - 未绑定:签发新 group_aid 并绑定
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
public_key | string | 是 | 公钥 DER base64(SPKI 格式) |
curve | string | 否 | 曲线名称(默认 P-256) |
响应:
{
"group": {
"group_id": "my-team.agentid.pub",
"group_aid": "my-team.agentid.pub",
...
},
"aid_cert": {
"cert": "-----BEGIN CERTIFICATE-----...",
"agentid": "my-team.agentid.pub"
}
}SDK 封装:
各语言 SDK 的 bindGroupAid 方法已实现幂等逻辑:
- 优先从 pending 槽位加载暂存密钥(崩溃恢复)
- 未命中则生成新密钥并暂存到 pending 槽位
- 调用 RPC 成功后导入 group_aid 身份并清理 pending 槽位
group.renew_group_aid
轮换群身份密钥。需要 owner 权限,且必须持有旧 group_aid 私钥。
用途:
- 群主密钥泄露后的安全轮换
- 定期密钥更新符合安全策略
验证:
- 服务端验证
renew_proof签名(用旧私钥签名 canonical payload) - 验证
old_public_key与当前 group_aid 证书匹配 - 签发新证书并更新 group_aid
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
group_aid | string | 否 | 群身份 AID(可选,服务端可推导) |
old_public_key | string | 是 | 旧公钥 DER base64 |
new_public_key | string | 是 | 新公钥 DER base64 |
curve | string | 否 | 新密钥曲线(默认 P-256) |
renew_proof | object | 是 | 轮换授权签名 |
renew_proof 结构:
{
"nonce": "随机 nonce(32 字符十六进制)",
"issued_ms": 1234567890000,
"signature": "用旧私钥签名的 base64"
}签名 canonical payload:
aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(new_public_key)}|{nonce}|{issued_ms}所有字段小写,用 | 分隔。
响应:
{
"group": {
"group_id": "my-team.agentid.pub",
"group_aid": "my-team.agentid.pub",
...
},
"aid_cert": {
"cert": "-----BEGIN CERTIFICATE-----...",
"agentid": "my-team.agentid.pub"
},
"old_cert_revoked": true
}SDK 封装:
各语言 SDK 的 renewGroupAid 方法自动处理:
- 加载旧 group_aid 私钥
- 生成新密钥对
- 用旧私钥签名 canonical payload
- 调用 RPC 并用新密钥覆盖本地 group_aid 身份
group.ban
封禁成员。被封禁者禁止发消息但保留成员身份,且不能重新加入(如先被移除再封禁)。需要 admin 及以上权限。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
subject | string | 是 | 要封禁的 AID(也接受 aid) |
reason | string | 否 | 封禁原因 |
expires_at | integer | 否 | 过期时间戳(0 = 永久) |
expires_in_seconds | integer | 否 | 相对过期秒数(0 = 永久) |
响应:
{
"group_id": "g-abc123.agentid.pub",
"ban": {
"group_id": "g-abc123.agentid.pub",
"subject": "spammer.agentid.pub",
"banned_by": "alice.agentid.pub",
"reason": "垃圾消息",
"expires_at": 0,
"created_at": 1234567890000
}
}group.unban
解除封禁。需要 admin 及以上权限。
参数:group_id(string,兼容字段,值使用目标态 group_aid),subject 或 aid (string)
响应:
{
"group_id": "g-abc123.agentid.pub",
"subject": "spammer.agentid.pub",
"status": "removed"
}group.get_banlist
获取封禁列表。需要 admin 及以上权限。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group_id": "g-abc123.agentid.pub",
"items": [
{
"group_id": "g-abc123.agentid.pub",
"subject": "spammer.agentid.pub",
"banned_by": "alice.agentid.pub",
"reason": "垃圾消息",
"expires_at": 0,
"created_at": 1234567890000
}
],
"total": 1,
"page": 1,
"size": 200
}入群流程
group.request_join
申请加入群组。根据群组 join_mode 设置,有三种结果分支。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
message | string | 否 | 申请留言 |
answer | string | 否 | 入群问题的答案 |
响应(三种分支):
1. 自动加入(open 模式或匹配自动批准规则):
{
"status": "joined",
"group": { ... },
"member": { ... }
}2. 需要回答问题(approval 模式但未提供答案):
{
"status": "question_required",
"question": "请描述你的用途"
}3. 待审批(approval 模式且已提供答案):
{
"status": "pending",
"request": {
"group_id": "g-abc123.agentid.pub",
"aid": "carol.agentid.pub",
"message": "请加我",
"answer": "...",
"status": "pending",
"created_at": 1234567890000,
"updated_at": 1234567890000,
"expires_at": 1234654290,
"reviewed_by": null,
"rejection_reason": null
}
}group.list_join_requests
列出待审批申请。需要 admin 权限。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
group_id | string | 是 | — | 群组标识;兼容字段,值语义为目标态 group_aid |
status | string | 否 | "pending" | "pending" / "approved" / "rejected" |
page | integer | 否 | 1 | 页码 |
size | integer | 否 | — | 每页数量 |
响应:
{
"group_id": "g-abc123.agentid.pub",
"items": [
{
"group_id": "g-abc123.agentid.pub",
"aid": "carol.agentid.pub",
"message": "请加我",
"status": "pending",
"created_at": 1234567890000,
"updated_at": 1234567890000
}
],
"total": 1,
"page": 1,
"size": 50
}group.review_join_request
审批单个申请。需要 admin 权限。使用 aid 定位申请(非 request_id)。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
aid | string | 是 | 申请人 AID |
approve | boolean | 否 | 批准或拒绝,默认 true |
reason | string | 否 | 拒绝原因 |
响应(批准时):
{
"status": "approved",
"request": { ... },
"group": { ... }
}响应(拒绝时):
{
"status": "rejected",
"request": {
"group_id": "g-abc123.agentid.pub",
"aid": "carol.agentid.pub",
"status": "rejected",
"reviewed_by": "alice.agentid.pub",
"rejection_reason": "不符合条件"
}
}group.batch_review_join_request
批量审批入群申请。需要 admin 权限。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
requests | array | 是 | 审批列表 |
requests 数组每项:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
aid | string | 是 | 申请人 AID |
approve | boolean | 是 | 批准或拒绝 |
reason | string | 否 | 拒绝原因 |
响应:
{
"results": [
{"aid": "carol.agentid.pub", "ok": true, "status": "approved", "request": { ... }},
{"aid": "dave.agentid.pub", "ok": false, "error": "not found"}
],
"success_count": 1,
"fail_count": 1
}group.create_invite_code
创建邀请码。需要 owner/admin 权限,或群规则允许成员邀请。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
code | string | 否 | 自定义邀请码(不提供则自动生成) |
max_uses | integer | 否 | 最大使用次数,默认 1,必须 > 0 |
expires_in_seconds | integer | 否 | 有效期(秒),默认由 invite_code_ttl_days 配置(7 天) |
响应:
{
"group_id": "g-abc123.agentid.pub",
"invite_code": {
"group_id": "g-abc123.agentid.pub",
"code": "ic-a1b2c3d4e5",
"created_by": "alice.agentid.pub",
"expires_at": 1235172690,
"max_uses": 10,
"used_count": 0,
"status": "active",
"created_at": 1234567890000
}
}group.use_invite_code
使用邀请码加入群组。
参数:code (string, 必填,自动转为小写)
响应:
{
"status": "joined",
"group": { ... },
"invite_code": { ... }
}group.list_invite_codes
列出群组的邀请码。需要 admin 权限。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
group.revoke_invite_code
撤销邀请码。需要 admin 权限。
参数:group_id(string,兼容字段,值使用目标态 group_aid),code (string)
设置与分发
group.set_settings
统一写入群参数。需要 admin 及以上权限。dispatch_mode 是群消息的应用层分发模式标签,会随 group.send 生成的消息持久化,并由 SDK 在解密后注入到消息顶层和 payload.dispatch_mode。
group.index 是保留设置 key,用于保存 owner/admin SDK 生成并签名的群索引。更新 indexed settings 时必须同包提交新的签名 group.index,并通过 expected_index_etag 做 CAS。
dispatch_mode 不是 group.send 的单次入参;要修改后续消息的模式,请通过 group.set_settings 更新群设置。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
settings | object | 是 | 要写入的设置键值 |
expected_index_etag | string | 写 group.index 时必填 | CAS 期望旧 etag;空字符串表示只允许创建首个 group.index |
settings["dispatch_mode"] | string | 否 | "broadcast" / "mention",默认 "broadcast" |
settings["rules.content"] | string | 否 | 群规则正文 |
settings["rules.attachments"] | array | 否 | 群规则附件稳定引用 |
settings["announcement.content"] | string | 否 | 群公告正文 |
settings["announcement.attachments"] | array | 否 | 群公告附件稳定引用 |
settings["join.attachments"] | array | 否 | 入群要求附件稳定引用 |
settings["{keyName}.content"] | string | 否 | 通用文档型 indexed setting 正文;keyName 需满足受控命名规则 |
settings["{keyName}.attachments"] | array | 否 | 通用文档型 indexed setting 附件稳定引用 |
settings["group.index"] | object | 更新 indexed settings 时必填 | 签名 group index,当前结构至少包含 body |
预定义群级参数:
| key | 类型 | 默认值 / 初始化逻辑 | 说明 |
|---|---|---|---|
name | string | 创建群时传入;兼容路径可能用 group_id 补齐 | 群名称 |
description | string | "" | 群描述 |
visibility | string | "private" | 群可见性:"public" / "private";旧值 "invite_only" 会映射为 "private" |
rules.content | string | "" | 群规则正文 |
rules.attachments | array | [] | 群规则附件 |
announcement.content | string | "" | 群公告正文 |
announcement.attachments | array | [] | 群公告附件 |
join.mode | string | 按 visibility 推导:public -> open,private -> approval | 入群模式:"open" / "approval" / "invite_only" / "closed" |
join.question | string | "" | 入群问题 |
join.auto_approve_patterns | array | [] | 自动批准 AID 匹配规则 |
join.max_pending | integer | 100 | 最大待审批入群申请数 |
join.attachments | array | [] | 入群材料附件稳定引用 |
dispatch_mode | string | "broadcast" | 群消息分发标签:"broadcast" / "mention";未显式设置时 get_settings 仍返回默认值 |
group.index | object | — | 保留 key;签名 JSONL 群索引,由 SDK 生成,服务端只校验、CAS 保存和返回 |
indexed settings:
| key | 说明 |
|---|---|
rules.content / rules.attachments | 群规则正文与附件稳定引用 |
announcement.content / announcement.attachments | 群公告正文与附件稳定引用 |
join.mode / join.question / join.auto_approve_patterns / join.max_pending / join.attachments | 入群要求配置与附件稳定引用 |
{keyName}.content / {keyName}.attachments | 通用文档型设置正文与附件稳定引用 |
写入规则:
- 只更新非 indexed settings 时,继续直接调用
set_settings,不需要group.index。 - 更新任意 indexed setting 时,必须在同一次
settings中携带签名group.index。 - 服务端只接受受控动态文档 key:
{keyName}.content/{keyName}.attachments,其中keyName匹配^[A-Za-z][A-Za-z0-9_-]{0,63}$,且不能使用join等保留前缀。调用方不能用该机制写任意 settings key。 - 写入
group.index时必须传expected_index_etag。 - 服务端在同一事务内比较当前
group.indexetag、写 indexed settings、写group.index。 - CAS 失败时错误消息包含
group.index etag conflict;SDK 的updateGroupIndex会重新读取当前 index、重建签名并按max_attempts重试。 rules.attachments、announcement.attachments、join.attachments和{keyName}.attachments只保存附件引用;附件实体应先写入群自有区,推荐路径为group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...。群自有区默认允许owner/admin写入,member默认不可写;.group/是系统控制目录,不允许授予role:member写权限。
await client.call("group.set_settings", {
"group_id": "g-abc123.agentid.pub",
"settings": {"dispatch_mode": "mention"},
})响应:
{
"group_id": "g-abc123.agentid.pub",
"group_aid": "g-abc123.agentid.pub",
"updated_keys": ["dispatch_mode"]
}写入 group.index 成功时,响应顶层会强制携带 _meta.group_indexes:
{
"group_id": "g-abc123.agentid.pub",
"group_aid": "g-abc123.agentid.pub",
"updated_keys": ["announcement.content", "group.index"],
"_meta": {
"group_indexes": {
"g-abc123.agentid.pub": {
"etag": "\"sha256:...\"",
"last_modified": 1780000000000,
"schema": "aun.group.index.v1"
}
}
}
}group.index 的正文格式:
{"type":"index_meta","group_aid":"g-abc123.agentid.pub","etag":"\"sha256:...\"","last_modified":1780000000000,"schema":"aun.group.index.v1","body_hash":"sha256:...","signed_by":"alice.agentid.pub","sig_alg":"ECDSA-P256-SHA256","signature":"base64..."}
{"key":"announcement.content","source":"db","etag":"\"sha256:...\"","last_modified":1780000000000}etag 和 body_hash 都由 index 条目的 canonical JSONL bytes 计算。signature 覆盖去掉 signature 字段后的 index_meta 和正文条目,signed_by 必须等于本次 RPC actor AID。服务端不会根据 DB 状态生成 group.index。
group.get_settings
统一读取群参数。成员可读;不传 keys 时返回核心群资料和 settings 表中的全部设置。未显式设置 dispatch_mode 时,服务端仍返回默认值 "broadcast"。读取 keys=["group.index"] 可从服务端摘取当前签名 group.index。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
keys | array | 否 | 只读取指定 key,如 ["dispatch_mode", "rules.content"];读取 ["group.index"] 时强制返回 _meta.group_indexes |
响应:
{
"group_id": "g-abc123.agentid.pub",
"group_aid": "g-abc123.agentid.pub",
"settings": [
{"key": "dispatch_mode", "value": "broadcast", "updated_at": 1234567890000}
]
}如果服务端已保存 group.index,普通 settings 读取可能在顶层返回 _meta.group_indexes。该 meta 受服务端注入频率控制;显式读取 group.index 时会强制返回:
{
"group_id": "g-abc123.agentid.pub",
"group_aid": "g-abc123.agentid.pub",
"settings": [
{"key": "group.index", "value": {"body": "..."}, "updated_by": "alice.agentid.pub", "updated_at": 1780000000000}
],
"_meta": {
"group_indexes": {
"g-abc123.agentid.pub": {
"etag": "\"sha256:...\"",
"last_modified": 1780000000000,
"schema": "aun.group.index.v1"
}
}
}
}SDK 观察到 _meta.group_indexes 只记录远端 etag,不会自动覆盖本地 index 或业务缓存。etag 不一致只表示本地与观察到的远端版本不同,方向由应用层决定:checkGroupIndex 用于检查是否不同步,getGroupIndex 用于显式 pull 远端 manifest 并同步本地缓存,updateGroupIndex 用于显式 CAS push 本地 indexed settings。
消息
group.send
发送群消息。需要 member 权限。
群消息的持久化 dispatch_mode 来自群设置,取值为 "broadcast" / "mention";服务端会写入消息对象并在 pull / push 中返回。运行时是否广播全员或分发给值班 Agent,由响应中的 dispatch / message_dispatch 描述。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
payload | object | 否 | 消息内容 |
type | string | 否 | 信封/封装类型,普通业务消息无需填写;SDK 加密群消息时自动使用 e2ee.group_encrypted |
attachments | array | 否 | 兼容旧接口的顶层附件元数据;推荐把业务附件放入 payload.attachments |
protected_headers / headers | object | 否 | SDK 加密前读取的 E2EE 信封元数据,类似 HTTP headers;推荐使用 protected_headers,headers 仅作为兼容别名;服务端不解释,接收端验 _auth 后在 e2ee.protected_headers 暴露 |
Payload 参考约定
group.send.params.payload 的统一业务负载格式见 09-payload-reference。完整群消息请求仍在 payload 同级传入 group_id(兼容参数名,值使用目标态 group_aid);业务类型放在 payload.type,不要与 group.send.params.type 信封/封装类型混用。
protected_headers 只在 SDK 加密路径生效;裸 RPC 发送明文或已加密信封时,调用方需自行遵守 05-E2EE加密通信 的格式和校验规则。
响应:
{
"group_id": "g-abc123.agentid.pub",
"message": {
"group_id": "g-abc123.agentid.pub",
"seq": 42,
"message_id": "uuid",
"sender_aid": "alice.agentid.pub",
"message_type": "e2ee.group_encrypted",
"dispatch_mode": "broadcast",
"payload": {"type": "e2ee.group_encrypted", "...": "..."},
"attachments": [],
"created_at": 1234567890000
},
"event": { ... },
"dispatch_mode": "broadcast",
"dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
"message_dispatch": { ... },
"envelope": {
"from": "alice.agentid.pub",
"group_id": "g-abc123.agentid.pub",
"type": "text",
"timestamp": 1234567890000,
"encrypted": true,
"payload_type": "text"
},
"payload": {"type": "text", "text": "Hello"}
}| 字段 | 类型 | 说明 |
|---|---|---|
group_id | string | 兼容字段,值语义为目标态 group_aid |
message | object | 消息对象(含 seq、message_id、sender_aid 等) |
event | object | 关联的群事件对象 |
dispatch_mode | string | 群消息持久化分发模式标签:"broadcast" / "mention";SDK 解密后也会注入到 payload.dispatch_mode |
dispatch | object | 分发策略:mode 为 "broadcast"(广播全员)或 "duty"(值班分发);reason 说明原因(如 "duty_disabled" / "active_duty" / "no_duty_candidate" 等) |
duty_state | object | 可选,值班模式下的当前状态 |
message_dispatch | object | 运行时分发结果;常见 status 包括 "broadcast"、"sent"、"queued_batch"、"debounced"、"skipped"、"failed" |
envelope | object | SDK 回填的发送结果信封,包含发送方、群标识、业务类型、时间戳、加密标志、protected headers 等可转发元数据 |
payload | object | SDK 回填的应用层业务 payload;裸 RPC 或内部 _skip_send_result_envelope 路径可能没有该字段 |
group.thought.put
写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 seq,不广播,不进入 group.pull,不需要 ack,也不持久化;只在内存中保留当前 head。
SDK 调用时必须走群组 E2EE。应用层传入明文 payload,SDK 会加密成 V2 e2ee.group_encrypted 信封、补齐 thought_id / timestamp,并附加 client_signature。裸 WebSocket 客户端若绕过 SDK,至少必须自行完成 V2 envelope、sender_signature、AAD 和 state commitment 生成;client_signature 按 Gateway 连接级身份语义携带。
存储键为规范化后的 group_aid + sender_aid + context.type + context.id。RPC 字段名仍为 group_id 以兼容旧客户端,但服务端会先规范化为目标态群标识;sender_aid 由服务端认证态派生,不能由客户端指定;context 是 thought head 的唯一 selector,推荐使用 {"type": "run", "id": "run-xxx"}。同一 (group_aid, sender_aid) 保留最近 N 个 context 对应的 head,N 由群服务配置 max_thought_heads_per_sender 控制,当前默认值为 100;同一个 head 下可追加多条 thought item。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
context.type | string | 是 | 思考的上下文类型,推荐 run |
context.id | string | 是 | 思考的上下文 ID,如 run_id |
payload | object | 是 | SDK 加密前的思考内容;推荐格式见 09-payload-reference |
encrypt | boolean | 否 | SDK 侧固定按 true 处理;false 会被拒绝 |
thought_id | string | 否 | thought item ID;不传时 SDK 生成 gt-* |
timestamp | integer | 否 | 客户端时间戳;不传时 SDK 生成 |
protected_headers / headers | object | 否 | SDK 加密前读取的 E2EE 信封元数据;推荐使用 protected_headers,headers 仅作为兼容别名;context 会被 SDK 复制进信封并单独验 _auth |
SDK 调用示例:
await client.call("group.thought.put", {
"group_id": "g-abc123.agentid.pub",
"context": {"type": "run", "id": "run-xxx"},
"payload": {"type": "thought", "text": "这是 Agent 自己的 run 级思考"},
})裸 RPC 加密后形态:
{
"group_id": "g-abc123.agentid.pub",
"context": {"type": "run", "id": "run-xxx"},
"thought_id": "gt-...",
"type": "e2ee.group_encrypted",
"encrypted": true,
"payload": {"type": "e2ee.group_encrypted", "version": "v2", "...": "..."},
"client_signature": { "...": "..." }
}响应:
{
"group_id": "g-abc123.agentid.pub",
"sender_aid": "alice.agentid.pub",
"context": {"type": "run", "id": "run-xxx"},
"thought_id": "gt-...",
"stored_count": 1,
"updated_at": 1234567890000
}group.thought.get
读取指定发送者针对指定群上下文的当前思考内容。SDK 会在返回应用层前自动解密。get 是查询操作,可重复调用;它不触发 push/pull、ack 或 replay 消费。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
sender_aid | string | 是 | thought 作者 AID |
context.type | string | 是 | 思考的上下文类型,推荐 run |
context.id | string | 是 | 思考的上下文 ID,如 run_id |
SDK 调用示例:
result = await client.call("group.thought.get", {
"group_id": "g-abc123.agentid.pub",
"sender_aid": "alice.agentid.pub",
"context": {"type": "run", "id": "run-xxx"},
})SDK 返回:
响应会原样包含本次查询使用的 selector(context)。
{
"found": true,
"group_id": "g-abc123.agentid.pub",
"sender_aid": "alice.agentid.pub",
"context": {"type": "run", "id": "run-xxx"},
"thoughts": [
{
"thought_id": "gt-...",
"message_id": "gt-...",
"context": {"type": "run", "id": "run-xxx"},
"payload": {"type": "thought", "text": "正在比较两个候选方案"},
"created_at": 1234567890000,
"e2ee": {"encryption_mode": "epoch_group_key"}
}
],
"updated_at": 1234567890000
}未找到当前 head 时,SDK 返回 found=false 且 thoughts=[]。
group.pull
增量拉取群消息。事件请用 group.pull_events 单独拉取。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
group_id | string | 是 | — | 群组标识;兼容字段,值语义为目标态 group_aid |
after_message_seq | integer | 否 | 0 | 从该消息 seq 之后拉取 |
limit | integer | 否 | 50 | 最大条数(最大 50;pull_max_limit 配置只能进一步收紧) |
device_id | string | 否 | — | 设备 ID(多设备模式) |
响应:
{
"group_id": "g-abc123.agentid.pub",
"messages": [ ... ],
"latest_message_seq": 42,
"has_more": false,
"limit": 50
}多设备模式时额外返回 cursor 对象(含 current_seq、join_seq、latest_seq、unread_count)。
返回的每条群消息包含 dispatch_mode。Python / Go / TS / JS SDK 在解密后会保留顶层 dispatch_mode,并把同一值注入到 payload.dispatch_mode,方便应用层按 "broadcast" / "mention" 做 UI 或通知策略。
group.ack
提交群消息已读游标。等同于 group.ack_messages,需要 device_id。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
device_id | string | 是 | 设备 ID |
msg_seq | integer | 是 | 确认到的消息序号 |
响应:
{"cursor": 42}group.recall
撤回群消息。仅原发送者可撤回自己的消息,受时间窗口限制(默认 120 秒,由群服务配置 recall_window_seconds 控制,0 表示不限制)。管理员撤回(group_admin_recall_enabled)默认关闭,本期不实现。
双 tombstone 机制:群消息使用 per-group 全局 message_seq(V1/V2 共享同一空间),直接删除原消息会让"还没拉到原消息"的客户端遇到永久 seq 空洞。因此撤回写入两条 tombstone:
- 原 seq 占位 tombstone:占住被撤消息原来的 seq。V1 把原
group_messages行message_type改为group.message_recalled并清空正文;V2 删除v2_group_messages密文体与所有v2_group_wraps,再在group_messages插入同original_seq的明文 tombstone 顶替。服务对象是还没读到原消息的客户端——拉到该 seq 看到 tombstone,而非空洞。 - 新 seq 通知 tombstone:分配一个新的
message_seq,通知已经读过原消息(游标已越过original_seq)的客户端"这条消息被撤回了"。
同时写一条 group_events(event_type = group.message_recalled)用于事件流审计,并在事务提交后推送 event/group.message_recalled(见下)。撤回真相记录在 group_message_recalls 表,(group_id, original_message_id) 与 (group_id, original_seq) 双唯一键防止重复撤回。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
message_ids | string[] | 是 | 待撤回消息 ID 列表,最多 100 个(recall_max_batch) |
reason | string | 否 | 可选撤回理由,建议短文本(最长 255 字符) |
响应:
{
"success": true,
"accepted": ["gm-aaa", "gm-bbb"],
"recalled": ["gm-aaa"],
"errors": [
{"message_id": "gm-bbb", "error": "not_sender"}
]
}| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 整体是否受理 |
accepted | string[] | 通过时间窗口前置过滤、进入撤回事务的消息 ID |
recalled | string[] | DB 真实撤回成功的消息 ID(避免并发撤回误通知) |
errors | array | 逐条错误:{message_id, error} |
逐条错误码:
| error | 说明 |
|---|---|
not_found | 消息不存在 |
not_sender | 操作者不是原发送者 |
already_recalled | 消息已被撤回(命中唯一键 / 占位 tombstone 已存在) |
expired | 超过撤回时间窗口 |
group_inactive | 群组非 active 状态(suspended / dissolved) |
SDK 行为:SDK 把 pull / push 收到的撤回 tombstone(占位与通知)归一化为 group.message_recalled 应用事件,不作为普通 group.message_created 交付;tombstone 仍占 seq,正常推进 SeqTracker 与 ack。SDK 按 (group_id, message_ids) 去重,因此即使同时收到在线 push 事件、占位 tombstone、通知 tombstone,应用层也只回调一次。去重键不含 recalled_at:占位 tombstone、通知 tombstone 与在线 push 三条通道对同一次撤回可能携带不同来源的时间戳(push 在事务提交后重取),若纳入 recalled_at 会使去重失效、导致重复回调;一条消息只能被撤回一次(服务端 group_message_recalls 唯一键保证),(group_id, message_ids) 已能唯一标识一次撤回。
所有语言 SDK 统一通过
client.call("group.recall", {...})调用,不提供独立的便捷方法名。
群文件系统
新代码统一使用 group.fs.*。路径为 POSIX 风格 group path:group_aid:/docs/a.md、https://{group_aid}/docs/a.md 或带 group_id 参数的裸路径。group_aid:/memberdata/{member_ref}/... 只由服务端映射到真实成员 storage,SDK 不拼接 group_data/{group_aid}。
推荐通过 SDK/CLI 使用:
| 语言 | 入口 |
|---|---|
| Python | client.group.fs |
| TypeScript / JavaScript | client.group.fs |
| Go | client.Group().FS() |
| CLI | aun group fs ... |
权限与签名约束:
- 群自有区是除
memberdata等系统保留路径外的整个group_aidnamespace。group_aid当前证书签名可写;成员角色中owner/admin默认可写,member默认不可写。group_aid:/.group/是系统控制目录,用于群公告、群规则、入群要求附件,默认允许owner/admin写入。 - 老群如果缺少
.group/默认 ACL,group 服务会在该群首次被 RPC 访问时 best-effort 触发 namespace/ACL lazy repair;只有本次 baseline ACL 全部同步成功才记录本进程已检查,失败会在后续访问继续重试。 group.fs.set_acl/group.fs.remove_acl/group.fs.get_acl/group.fs.list_acl只能由当前 groupowner/admin调用。当前支持grantee_aid="role:admin"与grantee_aid="role:member";role:member只能授予具体业务目录的rw权限,不能授予根目录或.group/,也不能获得删除、移动、重命名权限。成员升降级、退群、踢出不会联动授权或撤销目录 ACL。memberdata/{member_ref}写入默认只允许该成员本人;SDK 只传 group path,不拼接真实 storage 路径。- 上传控制面会透传
parents到 storage:默认parents=true时可递归创建父目录,显式parents=false时父目录必须已存在。 - JavaScript 浏览器版
cp(string, group)默认把 string 当文本内容上传;Node 本地路径需显式传sourceType: "path"、localPath: true或使用local:前缀。Python、TypeScript 和 Go 默认把 string 当本地路径。
group.fs.ls
列出目录。参数:path 必填;可选 page、size、marker、long、recursive。响应返回 group view items,节点 path 仍为 group path。
group.fs.find
查找节点。参数:path 必填;可选 pattern、name、type、size、mtime、page、page_size。
group.fs.stat
查看节点。参数:path 必填。响应为 NodeView。
group.fs.lstat
查看链接节点本身。参数同 group.fs.stat。
group.fs.df
查看群文件系统用量。参数可传 path 或 group_id。
group.fs.create_download_ticket
创建下载票据。参数:path 必填。响应包含 download_url、可选 sha256、content_type、file_name。SDK 下载数据面使用该票据执行 HTTP GET 并校验 sha256。
group.fs.set_acl
授予群自有区角色 ACL。需要当前 group owner/admin 身份调用;底层由 group 服务以内部门面写入 storage.set_acl。
参数:path 必填,指向群自有区路径;grantee_aid 可为 role:admin 或 role:member。role:admin 默认 rwx;role:member 只能为 rw,且只能授到具体业务目录,不能授到根目录或 .group/。path 可传 group_aid:/archive 等 group path。服务端写入 storage 内部权限位时会把 POSIX 删除位 x 映射为内部 d,对外响应仍显示 rwx;不授删除、移动、重命名权限时使用 rw。
group.fs.remove_acl
撤销群自有区角色 ACL。需要当前 group owner/admin 身份调用;底层由 group 服务以内部门面写入 storage.remove_acl。
参数:path 必填,指向群自有区路径;grantee_aid 可为 role:admin 或 role:member。撤销 role:member 后,member 不再因该目录 ACL 获得创建/写入权限。
group.fs.get_acl
查询群自有区角色 ACL。需要当前 group owner/admin 身份调用;普通 member 不能查询。参数:path 必填,指向群自有区路径;可传裸路径 + group_id,也可传完整 group_aid:/...。
响应包含 group_id、group_aid、path、area、storage 和 acls。acls[].perms 使用 POSIX 视图,删除权限显示为 x,因此授权 role:admin:rwx 后查询也返回 rwx;role:member 只应返回 rw。
group.fs.list_acl
group.fs.get_acl 的别名,参数、权限和返回结构完全相同。
group.fs.mkdir
创建目录。参数:path 必填;parents 可选,默认 false。
group.fs.rm
删除节点。参数:path 必填;recursive、force 可选。
group.fs.cp
只处理 group→group 远程复制。参数:src、dst 必填;force、recursive、follow_symlinks 可选。本地上传和下载由 SDK 的 cp 编排数据面,不直接调用此 RPC。
group.fs.mv
只处理 group→group 远程移动。参数:src、dst 必填;force 可选。本地路径参与时 SDK/CLI 应拒绝。
group.fs.check_upload
上传前检查。参数:path、size_bytes、sha256、content_type;可选 force、parents、expected_version、metadata。响应可包含 target_exists、within_limit、instant、dedup_hit 或 skip_upload。
group.fs.create_upload_session
创建上传会话。参数同 check_upload。响应包含 upload_url、session_id、可选 headers。SDK 使用该 URL 执行 HTTP PUT。
group.fs.complete_upload
完成上传。参数包含 path、sha256、size_bytes、可选 session_id、skip_blob、metadata、expected_version。响应为 group view NodeView。
group.fs.mount
挂载成员数据区。参数:path 必填;可选 readonly、require_approval、source_bucket、expires_at、volume_id。
group.fs.umount
卸载成员数据区。参数:path 必填。对成员数据区卸载不删除成员源数据。
在线状态
group.get_online_members
获取当前在线成员列表。
参数:group_id(string,必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group_id": "g-abc123.agentid.pub",
"total": 2,
"page": 1,
"size": 200,
"online_count": 2,
"members": [
{
"aid": "alice.agentid.pub",
"role": "owner",
"joined_at": 1234567890000,
"online": true,
"session_id": "sess_123",
"last_active_at": 1234567890000,
"expire_at": 1234571490
}
]
}兼容字段:items、online_members 与 members 内容完全相同;新实现应优先读取 members。
多设备游标
group.pull_events
增量拉取群事件,支持多设备独立游标。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
group_id | string | 是 | — | 群组标识;兼容字段,值语义为目标态 group_aid |
device_id | string | 否 | — | 设备 ID,多设备模式必填 |
device_name | string | 否 | — | 设备名称(首次注册时使用) |
device_type | string | 否 | — | 设备类型 |
after_event_seq | integer | 否 | 游标位置 | 从该事件 seq 之后拉取;多设备模式下默认使用设备游标 |
limit | integer | 否 | 50 | 最大条数(最大 50;pull_max_limit 配置只能进一步收紧) |
响应:
{
"group_id": "g-abc123.agentid.pub",
"events": [ ... ],
"latest_event_seq": 100,
"has_more": false,
"limit": 50,
"cursor": {
"current_seq": 50,
"join_seq": 0,
"latest_seq": 100,
"unread_count": 50
}
}
cursor仅多设备模式(提供device_id)时返回。响应大小受pull_max_response_bytes配置限制。包含 E2EE epoch 范围检查,不返回成员加入前的加密事件。
group.ack_messages
确认消息游标(多设备模式)。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
device_id | string | 是 | 设备 ID |
msg_seq | integer | 是 | 确认到的消息序号 |
响应:{ "cursor": 123 }
不能确认加入位置之前的消息;序号自动截断到群组当前最大消息序号。
group.ack_events
确认事件游标(多设备模式)。
参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id | string | 是 | 群组标识;兼容字段,值语义为目标态 group_aid |
device_id | string | 是 | 设备 ID |
event_seq | integer | 是 | 确认到的事件序号 |
响应:{ "cursor": 456 }
group.list_devices
列出当前用户在指定群组的所有设备及游标状态。
参数:group_id(必填;兼容字段,值使用目标态 group_aid)
响应:
{
"devices": [
{
"device_id": "device-123",
"device_name": "My Phone",
"device_type": "mobile",
"last_pull_at": 1234567890000,
"msg_unread": 10,
"event_unread": 5
}
]
}group.unregister_device
注销设备游标(清理不再使用的设备记录)。
参数:group_id(必填;兼容字段,值使用目标态 group_aid),device_id (必填)
响应:{ "success": true }
管理辅助
group.get_admins
获取管理员列表(owner + admin 角色)。
参数:group_id(必填;兼容字段,值使用目标态 group_aid)
响应:
{
"admins": [
{
"aid": "alice.agentid.pub",
"role": "owner",
"member_type": "human",
"joined_at": 1234567890000
}
]
}group.get_master
获取群主 AID。
参数:group_id(必填;兼容字段,值使用目标态 group_aid)
响应:{ "group_id": "g-abc123.agentid.pub", "owner_aid": "alice.agentid.pub" }
group.get_summary
获取群组综合统计摘要。
参数:group_id(必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group_id": "g-abc123.agentid.pub",
"name": "My Group",
"owner_aid": "alice.agentid.pub",
"status": "active",
"visibility": "private",
"member_count": 10,
"human_count": 7,
"ai_count": 3,
"admin_count": 2,
"online_count": 5,
"message_seq": 1000,
"event_seq": 2000,
"e2ee_epoch": 3,
"created_at": 1234567890000,
"updated_at": 1234567890000
}group.refresh_member_types
刷新成员类型分类统计。
参数:group_id(必填;兼容字段,值使用目标态 group_aid)
响应:
{
"group_id": "g-abc123.agentid.pub",
"total": 10,
"human_count": 7,
"ai_count": 3,
"members": [
{ "aid": "alice.agentid.pub", "role": "owner", "member_type": "human" }
]
}事件
event/group.created
群组创建时推送。
Payload:
{
"module_id": "group",
"group_id": "g-abc123.agentid.pub",
"owner_aid": "alice.agentid.pub",
"visibility": "private"
}event/group.changed
群组状态变化时推送。
Payload:
{
"envelope": {
"module_id": "group",
"action": "member_added",
"group_id": "g-abc123.agentid.pub",
"event_seq": 42
},
"module_id": "group",
"action": "member_added",
"group_id": "g-abc123.agentid.pub",
"event_seq": 42
}SDK 交付给应用层的群事件信封字段统一放在 envelope。0.5.x 当前仍保留顶层 module_id / action / group_id / event_seq 等兼容别名;新代码应优先通过 ev["envelope"]["action"] 等路径访问。
| 字段 | 类型 | 说明 |
|---|---|---|
envelope | object | 群事件信封,包含 module_id、action、group_id、event_seq、event_type、actor_aid、created_at、device_id、slot_id 等存在的字段 |
module_id | string | 固定 "group" |
action | string | 变更类型(见下表) |
group_id | string | 兼容字段,值语义为目标态 group_aid |
event_seq | integer | 可选,服务端分配的单调递增序号,用于 SDK 内部保序去重 |
path | string | 可选,Group FS 相关 action 的节点路径 |
保序去重(SDK 内部行为):
服务端为每条 group.changed 事件分配 event_seq(按群 group_event:{group_id} 命名空间单调递增)。SDK 收到事件后:
- 去重:
event_seq≤ 已连续消费序号,或已处理过该序号,则丢弃 - 保序:事件入有序队列,按序号连续后才发布给应用层
- 补洞:检测到序号空洞时,自动调用
group.pull_events拉取缺失事件补齐 - ack:连续段推进后自动发送
group.ack_events(namespacegroup_event:{group_id})
不携带 event_seq 的旧格式事件直接发布,不参与保序(兼容旧服务端)。
action 取值:
| action | 说明 |
|---|---|
upsert | 群组创建/更新 |
update | 群组信息更新 |
member_added | 成员加入 |
member_left | 成员退出 |
member_removed | 成员被踢出 |
role_changed | 角色变更 |
owner_transferred | 群主转让 |
rules_updated | 规则更新 |
announcement_updated | 公告更新 |
join_requested | 收到入群申请 |
joined | 成员加入(通过邀请码等) |
join_approved | 入群申请批准 |
join_rejected | 入群申请拒绝 |
join_requirements_updated | 入群要求更新 |
invite_code_created | 邀请码创建 |
invite_code_used | 邀请码使用 |
invite_code_revoked | 邀请码撤销 |
member_banned | 成员封禁 |
member_unbanned | 成员解封 |
suspended | 群组暂停 |
resumed | 群组恢复 |
dissolved | 群组解散 |
订阅:
client.on("group.changed", lambda ev: print(ev["action"]))event/group.message_created
群消息创建时推送给所有在线成员。支持两种模式:
消息推送模式(带 payload):
{
"module_id": "group",
"group_id": "g-abc123.agentid.pub",
"seq": 42,
"message_id": "uuid",
"sender_aid": "alice.agentid.pub",
"type": "e2ee.group_encrypted",
"dispatch_mode": "broadcast",
"payload": { "type": "e2ee.group_encrypted", "..." : "..." },
"dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
"kind": "group.broadcast",
"member_aids": ["bob.agentid.pub"],
"proximity": {
"same_device": false,
"same_egress_ip": true,
"same_network": true,
"basis": "egress_ip",
"asserted_by": "gateway"
},
"same_device": false,
"same_egress_ip": true,
"same_network": true
}SDK 收到后自动解密 payload,解密后的明文消息直接交付用户回调。
通知模式(不带 payload):
{
"module_id": "group",
"group_id": "g-abc123.agentid.pub",
"seq": 42,
"message_id": "uuid",
"sender_aid": "alice.agentid.pub",
"type": "e2ee.group_encrypted",
"dispatch_mode": "broadcast",
"dispatch": {"mode": "broadcast", "reason": "duty_disabled"}
}SDK 收到后自动调用 group.pull 拉取最新消息并逐条解密后交付用户回调。
SDK 应用层回调形态:
{
"envelope": {
"group_id": "g-abc123.agentid.pub",
"from": "alice.agentid.pub",
"type": "text",
"timestamp": 1234567890000
},
"group_id": "g-abc123.agentid.pub",
"seq": 42,
"message_id": "uuid",
"sender_aid": "alice.agentid.pub",
"message_type": "group.message",
"dispatch_mode": "broadcast",
"payload": {"type": "text", "text": "Hello"}
}SDK 交付给应用层的 payload 是明文业务 JSON 对象;群消息信封字段统一放在 envelope。envelope 只保留可转发的归一化元数据,from 由 sender_aid 归一化而来,timestamp 由 created_at / t_server 归一化而来。0.5.x 当前仍保留顶层 group_id / seq / message_id / sender_aid / dispatch_mode 等兼容别名;新代码应优先通过 msg["envelope"]["from"]、msg["envelope"]["timestamp"] 等路径访问。Gateway 可能附加 proximity 及 same_device / same_egress_ip / same_network,表示由 Gateway 基于连接上下文判断的近端关系提示,不参与 E2EE AAD 或业务鉴权。
event/group.message_recalled
群消息撤回后推送给所有在线成员(与 pull 双 tombstone 兜底互补)。在线 push 是实时通道,双 tombstone 是离线 / 未读 / push 丢失时的可靠性兜底;两者最终一致,SDK 去重保证应用层只感知一次。
Payload:
{
"envelope": {
"group_id": "g-abc123.agentid.pub",
"from": "alice.agentid.pub",
"type": "group.message_recalled",
"kind": "group.message_recalled",
"timestamp": 1234567890000
},
"module_id": "group",
"group_id": "g-abc123.agentid.pub",
"seq": 43,
"message_id": "grm-uuid",
"tombstone_message_id": "grm-uuid",
"message_ids": ["gm-aaa"],
"target_message_seqs": [42],
"sender_aid": "alice.agentid.pub",
"recalled_by": "alice.agentid.pub",
"recalled_at": 1234567890000,
"reason": "",
"member_aids": ["bob.agentid.pub"]
}SDK 交付给应用层的撤回事件同样带 envelope。envelope 表示当前交付的撤回 tombstone / 通知自身信封,不是被撤回原消息的信封;业务侧被撤回的原消息列表继续使用 message_ids / target_message_seqs。message_id / seq 继续只保留在顶层兼容字段中,不进入 envelope。0.5.x 当前仍保留顶层 group_id / seq / message_id / sender_aid 等兼容别名;新代码应优先读取 envelope、message_ids 和 target_message_seqs。
| 字段 | 类型 | 说明 |
|---|---|---|
envelope | object | 撤回 tombstone / 通知自身信封,包含 group_id、from、type、kind、timestamp、encrypted、context、protected_headers 等存在的字段 |
module_id | string | 固定 "group" |
group_id | string | 兼容字段,值语义为目标态 group_aid |
seq | integer | 当前交付的撤回 tombstone / 通知 seq;在线 push 为 notice_seq,原 seq 占位 tombstone 为原消息 seq |
message_id | string | 当前交付的撤回 tombstone / 通知自己的 message_id |
tombstone_message_id | string | 兼容别名,等同于撤回 tombstone / 通知自身的 message_id |
message_ids | string[] | 被撤回的原消息 ID 列表 |
target_message_seqs | integer[] | 被撤回的原消息 seq 列表 |
sender_aid | string | 原消息发送方 |
recalled_by | string | 撤回操作者 |
recalled_at | integer | 撤回时间戳(毫秒) |
reason | string | 可选撤回理由 |
跨域成员通过 federation forward 转发(group.message_recalled 在跨域转发白名单内),路径与 group.message_created 一致。
订阅:
client.on("group.message_recalled", lambda ev: print("recalled:", ev["message_ids"]))错误码
Group 服务定义了以下专用错误码(-33xxx 段):
| 错误码 | 含义 | 客户端处理建议 |
|---|---|---|
| -33001 | Group not found | 检查 group_id 是否正确 |
| -33002 | Group suspended | 等待恢复或联系管理员 |
| -33003 | Group closed | 不重试,群已解散 |
| -33004 | Already a member | 无需处理 |
| -33005 | Not a member | 需先加入群组 |
| -33006 | Invite code invalid or expired | 获取新邀请码 |
| -33007 | Join request pending | 等待审批,勿重复提交 |
| -33008 | Group FS path not found | 检查 path |
| -33009 | Resource request not found | 检查 request_id |
SDK 客户端将 -33001 映射为
GroupNotFoundError,-33002~-33003 映射为GroupStateError,其余映射为GroupError。未识别的错误码 fallback 到AUNError。

