ClouisleClouisle

团队与成员

创建团队、管理成员角色、授权模型并转让所有权

团队是 Clouisle 的资源隔离边界:Agent、工作流、知识库、工具、Skill 都归属某个团队。团队内的一切操作都要同时通过「全局权限码」和「团队成员角色门限」两层检查。

本页覆盖团队的创建、成员增删改、离开、所有权转让、删除,以及每步的失败原因。角色权限的完整模型见 角色与权限 与 权限与角色参考。

创建团队

创建团队需要全局 admin:team:create 权限,入口在管理台 Teams(/teams)页面。Member / Viewer 看不到该入口(/teams 需要 admin:team:read)。

  1. 进入 Admin → Teams。
  2. 点击 Create Team,填写:
    • Team Name(必填,全局唯一,重复返回 team_name_exists)
    • Description(可选)
    • Team Avatar(可选,从本地上传图片,支持 JPEG/PNG/GIF/WebP/SVG/ICO,建议 200×200、上限 10 MB;上传结果写入 avatar_url)
  3. 保存,调用 POST /api/v1/admin/teams。
  4. 创建者自动成为该团队的 owner(同时写入一条 role=owner 的 TeamMember)。

未实现 / Roadmap:创建时指定其他所有者、添加初始成员、邀请/加入设置、资源配额均不在创建流程内。成员需创建后通过添加成员加入;所有权通过转让所有权转移。

创建后在团队切换器里选择它。新建 Agent、工作流、知识库时确认当前团队,否则资源会落到错误的团队里,后续只能靠跨团队共享(仅工具支持)或重建来纠正。

团队管理页
团队管理页

两个团队界面

团队切换器提供两个入口,权限与能力完全不同:

入口路由需要用途
管理全部团队 (系统后台)/teams全局 admin:team:read列出系统内所有团队(分页、可按名称/描述搜索,默认 page_size=50)、创建、改信息、删除、批量删除;后端为 GET/POST/DELETE /api/v1/admin/teams
管理当前团队/app/team页面本身只要求是该团队成员(team:read);入口链接仅在超管或「团队 owner/admin 且持有 team:manage」时出现成员管理、团队基本信息编辑、离开、转让所有权、查看已授权模型(只读)

/app/team 页面的模型授权页签是只读的:展示当前团队已授权的模型、启用状态与今日用量/限额,并提示由系统管理员分配。模型授权的写操作全部要求超管(见下)。

团队详情与成员

团队概览

/app/team 头部显示团队头像、名称、默认团队 徽标(is_default)以及你在该团队内的角色徽标。成员页签列出用户名、邮箱、角色与加入时间,并支持按用户名/邮箱本地过滤。

未实现 / Roadmap:团队详情不显示资源配额(Agent/工作流/存储上限)、使用活动统计(对话数、执行数、API 调用),也没有团队级通知设置或独立资源页签。

模型授权

模型授权是超管专属能力,全部写接口都要求 get_current_active_superuser:

操作端点权限
查看团队已授权模型GET /api/v1/teams/{team_id}/models团队成员(或超管)
授权模型POST /api/v1/teams/{team_id}/models超管
批量授权POST /api/v1/teams/{team_id}/models/batch超管
修改配额/启用状态/优先级PUT /api/v1/teams/{team_id}/models/{model_id}超管
撤销授权DELETE /api/v1/teams/{team_id}/models/{model_id}超管
批量撤销DELETE /api/v1/teams/{team_id}/models/batch超管
列出可授权模型GET /api/v1/teams/{team_id}/available-models超管

管理台团队详情里的模型授权页签提供同一批操作,前端按 is_superuser || admin:model:update 控制按钮。可配置项包括每日/每月 Token 上限、每日/每月请求上限、is_enabled 与 priority。授权或撤销会向团队发送 team.model_granted / team.model_revoked 通知。细节见管理团队模型。

添加成员

需要全局 team:manage,且你在该团队内是 owner 或 admin(require_team_admin=True)。Member / Viewer 调用会得到 403 team_admin_required。

  1. 打开 /app/team 的成员页签,点击 添加成员(仅在有管理能力时显示)。
  2. 在「用户名或邮箱」输入目标用户的完整用户名或邮箱。
  3. 选择角色:Admin、Member、Viewer(不提供 Owner)。
  4. 点击确认,调用 POST /api/v1/teams/{team_id}/members。

匹配规则与后端校验:

情况结果
用户名精确匹配,或邮箱不区分大小写精确匹配命中用户
都匹配不到user_not_found,HTTP 404
只输入片段(如 john 前缀)匹配不到,报 404——没有模糊搜索/下拉选人
用户已经是成员already_team_member
角色选 ownercannot_add_as_owner
角色选 admin,但目标用户没有全局 team:manageoperation_not_permitted,HTTP 403(permission: team:manage)

给团队 admin 之前先给全局角色

把一个没有全局 team:manage 的用户加为团队 admin 会直接被拒。顺序必须是:先在 Admin → Users 给他 Team Admin 角色(或任何含 team:manage 的角色),再回团队里设为 admin。

添加成功后:新成员收到 team.member_added 通知,团队也收到一条汇总通知;成员身份立即生效,没有邀请/接受流程。

改变成员角色

只有团队 owner(或超管)能改角色。团队 admin 调用会得到 403 team_owner_required。

  1. 在成员列表找到目标成员,打开 ... 菜单。
  2. 选择 改变角色,在新角色下拉中选 Admin / Member / Viewer。
  3. 保存,调用 PUT /api/v1/teams/{team_id}/members/{user_id}。

后端校验顺序:

情况结果
调用者不是 owner(也不是超管)team_owner_required,HTTP 403
目标成员当前是 ownercannot_change_owner_role——所有者角色不可被修改,只能走转让所有权
新角色选 ownercannot_promote_to_owner——提升所有者只能走转让所有权
新角色选 admin,但目标用户没有全局 team:manageoperation_not_permitted,HTTP 403
目标用户不是该团队成员team_member_not_found,HTTP 404

变更成功后目标用户收到 team.role_changed 通知。

成员角色变更不写审计日志:团队审计只覆盖 create_team / update_team / delete_team / add_team_member / remove_team_member 与团队模型授权动作。

前端还会额外隐藏按钮:canActOnMember 要求「你不是被操作对象」且「你是 owner,或对方不是 admin」。因此团队 admin 看不到其他 admin 与 owner 的操作菜单,任何人都看不到自己的菜单项。

移除成员

DELETE /api/v1/teams/{team_id}/members/{user_id} 有两种路径:

场景所需权限说明
移除他人全局 team:manage + 团队 owner/admin前端菜单同样受 canActOnMember 限制
移除自己仅 team:read自移除不需要管理权限(等价于离开团队)

共同限制:owner 永远不能被移除(cannot_remove_owner,包括自己);目标不是成员时 team_member_not_found(404)。

移除后:该用户立即失去该团队全部资源访问权限;只删除团队成员关系,不会删除他的对话、API Key 或个人资源(对话因失去团队访问权而不可再访问)。团队收到 team.member_removed 通知,被移除者也会收到通知。之后可以重新添加。

离开团队

  1. /app/team → 设置 页签 → 危险区域,点击 离开团队。
  2. 在确认对话框中确认,调用 POST /api/v1/teams/{team_id}/leave(只需 team:read)。

owner 不能离开团队:接口返回 owner_cannot_leave,前端在危险区域显示提示「作为团队所有者,你无法直接退出团队,请先转移所有权」。想走就必须先转让所有权。另外默认团队(is_default=true)在前端不显示离开按钮——但这是 UI 行为,后端接口本身不会因为 is_default 而拒绝。

离开后你失去该团队资源访问权;已有对话保留。团队列表会刷新,页面跳回 /app。

转让所有权

需要全局 team:manage 且在该团队内是 owner/admin,同时必须是 owner(或超管)。团队 admin 调用返回 403 team_owner_required。

  1. 打开 /app/team 成员列表,找到目标成员,... → 转让所有权(该菜单项只有 owner 能看到)。
  2. 确认对话框点击确认,调用 POST /api/v1/teams/{team_id}/transfer-ownership?new_owner_id={user_id}。

后端规则(顺序执行):

  1. 目标必须是该团队成员,否则 team_member_not_found(404)。
  2. 目标必须已经持有全局 team:manage,否则 operation_not_permitted(403)。同样地,先给全局角色,再转让。
  3. 目标就是当前 owner → cannot_promote_to_owner(400)。
  4. 原 owner 的成员角色被降级为 admin,目标的成员角色改为 owner,并同步更新 Team.owner 字段。
  5. 新旧 owner 各收到一条 team.ownership_transferred 通知。

转让是不可逆的即时操作:原先的 owner 只剩 admin 权限,且无法自行改回(改角色要求 owner)。确认目标人选后再执行。

编辑团队信息

需要全局 team:update 且在该团队内是 owner/admin(PUT /api/v1/teams/{team_id})。

  • /app/team → 设置 页签:可改团队名称、描述、头像(未通过校验时输入框禁用)。
  • 管理台 /teams 的编辑对话框:同一批字段,需 admin:team:update。

字段与约束:name 必填且全局唯一(重复 → team_name_exists);description 可选;avatar_url 由上传组件写入。没有团队 slug、别名、域名等字段。

删除团队

删除团队是不可逆的破坏性操作,只能在管理台 /teams 执行,需要 admin:team:delete。团队 owner 在 /app/team 里没有删除入口。

  1. 在 /teams 列表点击目标团队的 ... → Delete Team(默认团队不显示该项)。
  2. 确认对话框点击确认,调用 DELETE /api/v1/admin/teams/{team_id}。对话框只要求确认,不需要输入团队名。
  3. 默认团队(is_default=true)被拒绝:cannot_delete_default_team。

删除影响(模型外键级联,已核对 models/*.py):

会被删除会被保留
团队记录与全部 TeamMember 成员关系成员的用户账户
该团队的 Agent、工作流、知识库、工具、Skill、资产审计日志(合规用途)
团队模型授权(TeamModel)、工具配置、通知、导入会话成员的账户数据(API Key 归属用户个人,不随团队删除)
Agent 会话及其消息(随 Agent 级联)—

团队角色与权限

团队角色是四个固定值 owner / admin / member / viewer,不携带任何权限代码,只作为团队门限。实际能力 = 全局角色权限 ∩ 团队门限。

门限规则

  • TEAM_MANAGEMENT_PERMISSIONS = team:update、team:manage、team:delete、tool:delete:这些动作必须同时具备全局权限码且在该团队内是 owner/admin。
  • 团队 viewer 只允许 team:read、agent:read/agent:chat、workflow:read/workflow:run/workflow:execute、kb:read/kb:test、tool:read/tool:execute、skill:read/skill:execute、conversation:read,其余写操作一律 403 operation_not_permitted。
  • 超管(is_superuser)直接绕过成员关系与团队门限。

团队管理权限

操作OwnerTeam AdminMemberViewer
查看团队与成员✓✓✓✓
改团队信息(名称/描述/头像)✓✓✗✗
添加成员✓✓✗✗
改变成员角色✓✗✗✗
移除成员✓✓(不能动其他 admin/owner)✗✗
离开团队✗(须先转让)✓✓✓
转让所有权✓✗✗✗
删除团队✗(需管理台 admin:team:delete)✗✗✗

团队内资源权限

操作OwnerTeam AdminMemberViewer
创建 Agent / 工作流 / 知识库✓✓✓✗
编辑他人的 Agent / 工作流 / 知识库✓✓✗✗
删除 Agent、发布 Agent 与工作流✓✓✗✗
与 Agent 对话、运行工作流✓✓✓✓
创建/编辑自己的工具与 Skill✓✓✓✗
编辑他人的工具 / Skill✓✓✗✗
删除工具✓✓✗(团队门限拒绝,尽管 Member 持有 tool:delete)✗
知识库检索/测试、上传/重命名/删除文档✓✓✓只读检索
执行工具与 Skill✓✓✓✓

API Key 不属于团队

API Key 通过 user_id 归属个人,列表接口对非超管强制只看自己的 Key,ensure_api_key_owner() 也要求「本人或超管」。团队成员角色对 API Key 没有任何影响,团队 owner/admin 也看不到、撤销不了别人的 Key。

默认团队角色

站点设置 default_team_id 指定默认团队,default_team_role 指定新用户加入时的成员角色,只接受 viewer / member / admin(其他值回退为 member,默认值也是 member)。新用户注册与 SSO 自动创建时触发,已存在的成员关系不会被覆盖。owner 永远不会被自动分配。

自定义团队角色

未实现。 团队只有 owner、admin、member、viewer 四个固定角色,每个角色对应一组固定门限规则,不能为单个团队增删权限。需要精细权限时改用全局自定义角色(见 角色与权限)。

团队协作与通知

团队协作通过共享资源实现:Agent、工作流、知识库、工具、Skill 在团队内共享,成员按角色门限访问。工作流执行历史对团队成员可见(受权限约束),可以看到谁在何时运行过。

团队相关自动通知(发送渠道由管理员在站点设置里配置,见通知与外部渠道):

类型触发时机接收方
team.member_added添加成员新成员 + 团队
team.member_removed移除成员被移除者 + 团队
team.role_changed改变成员角色被变更者
team.ownership_transferred转让所有权新旧 owner 各一条
team.model_granted / team.model_revoked模型授权 / 撤销团队

未实现 / Roadmap:没有按团队的通知配置,没有 @提及、共享对话、团队活动流、文档评论或团队内消息。

故障排除

无法访问团队资源

  1. 确认左侧团队切换器选中了正确的团队。
  2. 确认你是该团队成员(/app/team 能打开说明是;否则 not_team_member)。
  3. 确认全局角色含所需权限码;团队 viewer 只能读与执行。
  4. 确认资源 visibility:private 资源对非创建者返回 agent_access_denied / tool_access_denied。

无法改变角色 / 菜单里没有「改变角色」

  • 只有 owner(或超管)能改角色;team admin 会拿到 team_owner_required。
  • 前端还会隐藏:你不能操作自己,team admin 看不到其他 admin 与 owner 的操作菜单。
  • 目标是 owner 时不可改(cannot_change_owner_role),要换人只能转让所有权。
  • 想把某人升为团队 admin,他必须已有全局 team:manage。

加成员报 404 user_not_found

输入必须是完整用户名或完整邮箱(邮箱忽略大小写)。片段、昵称、显示名都匹配不到——系统不做模糊搜索。

加成员报 403 operation_not_permitted

角色选了 admin,但目标用户没有全局 team:manage。先给他 Team Admin 全局角色,再设为团队 admin。

转让所有权被拒

  • team_owner_required:你不是 owner(也不是超管)。
  • team_member_not_found:目标不是团队成员,先加成员。
  • operation_not_permitted:目标没有全局 team:manage。
  • cannot_promote_to_owner:目标已经是 owner。

无法离开团队 / 没有离开按钮

owner 不能离开(owner_cannot_leave),默认团队在前端不显示该按钮。先转让所有权;默认团队需要管理员先在站点设置里改默认团队。

无法删除团队

  • 需要 admin:team:delete,入口只在管理台 /teams。
  • 默认团队被拒绝:cannot_delete_default_team。

角色变更后权限没变

浏览器缓存的前端权限快照可能过期:刷新页面或重新登录即可。后端每次请求实时查库,不需要等缓存过期。

API 端点

团队接口使用 JWT 用户会话认证(不接受 API Key)。

平台侧(/api/v1/teams):

方法路径用途权限 / 门限
GET/api/v1/teams/my列出当前用户所属团队及角色登录即可
GET/api/v1/teams/{team_id}团队详情(含成员列表)team:read + 成员关系
PUT/api/v1/teams/{team_id}改名称/描述/头像team:update + owner/admin
POST/api/v1/teams/{team_id}/members添加成员(identifier 或 user_id + role)team:manage + owner/admin
PUT/api/v1/teams/{team_id}/members/{user_id}改成员角色team:manage + owner/admin,且调用者是 owner/超管
DELETE/api/v1/teams/{team_id}/members/{user_id}移除成员(自己 = 退出)移除他人:team:manage + owner/admin;移除自己:team:read
POST/api/v1/teams/{team_id}/leave主动离开团队team:read,owner 被拒
POST/api/v1/teams/{team_id}/transfer-ownership?new_owner_id=…转让所有权team:manage + owner/超管;目标须持有全局 team:manage

管理侧(/api/v1/admin/teams):

方法路径用途权限
GET/api/v1/admin/teams列出全部团队(page/page_size,默认 50;search 匹配名称或描述)admin:team:read
POST/api/v1/admin/teams创建团队(创建者为 owner)admin:team:create
DELETE/api/v1/admin/teams/{team_id}删除团队admin:team:delete,默认团队被拒

没有 GET /api/v1/teams(列出全部团队)这个端点。要遍历系统内所有团队,用管理侧的 GET /api/v1/admin/teams。

常见错误码

msg_keyHTTP含义与处理
team_not_found404团队不存在
not_team_member403调用者不是该团队成员
team_admin_required403需要团队 owner/admin
team_owner_required403该操作仅团队 owner(或超管)可做
operation_not_permitted403缺全局权限码(响应带 permission 字段)
team_name_exists400团队名重复
user_not_found404加成员时标识符匹配不到用户
already_team_member400用户已是团队成员
cannot_add_as_owner400不能用「添加成员」直接设为 owner
cannot_change_owner_role400不能修改 owner 的成员角色
cannot_promote_to_owner400不能用改角色或把所有权转给自己来提升为 owner
cannot_remove_owner400不能移除 owner(含自己移除自己)
owner_cannot_leave400owner 必须先转让所有权才能离开
team_member_not_found404目标用户不是该团队成员
cannot_delete_default_team400默认团队不能删除
team_model_already_authorized400该模型已授权给此团队
team_model_not_found404团队模型授权不存在

完整的请求/响应结构与代码示例见 Teams API。

参见:

这篇文章对你有帮助吗?

本页目录