This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/ICD/personas.md
2026-03-11 14:45:37 +00:00

5.9 KiB

Personas

A Persona is the unit of access control and AI identity: system prompt + model + provider config + KB bindings + grant scoping. Users interact with Personas, not raw provider configs. Admins curate which Personas are available; team admins create team-scoped Personas.

Model inheritance: A Persona inherits all properties of its underlying model. This includes context window size, max output tokens, supported capabilities (thinking, tools, vision, streaming), input/output pricing, and provider status. When the frontend displays a Persona, it resolves the underlying model's capabilities and shows the same pills/badges (e.g. thinking, tools, 200k context) that the raw model would show. The Persona adds identity (name, avatar, system prompt, KB bindings) on top of the model's capabilities — it never masks or reduces them.

Three scopes, three route namespaces, one domain:

Scope Routes Who manages
Personal GET/POST/PUT/DELETE /personas The user
Team GET/POST/PUT/DELETE /teams/:teamId/personas Team admin
Global (admin) GET/POST/PUT/DELETE /admin/personas Platform admin

All three return the same Persona object shape:

{
  "id": "uuid",
  "name": "Code Reviewer",
  "description": "Reviews code for bugs and style",
  "system_prompt": "You are a senior code reviewer...",
  "model": "claude-sonnet-4-20250514",
  "provider_config_id": "uuid|null",
  "scope": "personal|team|global",
  "owner_id": "uuid|null",
  "is_default": false,
  "is_active": true,
  "avatar_url": "/api/v1/personas/uuid/avatar?v=123",
  "inherited": {
    "context_window": 200000,
    "max_output_tokens": 8192,
    "supports_vision": true,
    "supports_tools": true,
    "supports_thinking": true,
    "supports_streaming": true,
    "input_price_per_m": 3.00,
    "output_price_per_m": 15.00,
    "provider_status": "healthy|degraded|down|null"
  },
  "created_at": "...",
  "updated_at": "..."
}

The inherited block is populated by the backend from the resolved model capabilities at response time — it is not stored on the persona. If the underlying model's capabilities change (e.g. provider upgrades context window), the persona inherits the new values automatically. The frontend uses inherited to render capability pills and context size badges identical to the raw model.

Personal Personas

Gated by allow_user_personas policy.

GET    /personas                     → { "personas": [...] }
POST   /personas                     ← { "name", "description", "system_prompt", "model", ... }
PUT    /personas/:id                 ← partial update
DELETE /personas/:id

Team Personas

GET    /teams/:teamId/personas       → { "personas": [...] }
POST   /teams/:teamId/personas       ← same shape
PUT    /teams/:teamId/personas/:id
DELETE /teams/:teamId/personas/:id

Admin (Global) Personas

GET    /admin/personas                → { "personas": [...] }
POST   /admin/personas                ← same shape
PUT    /admin/personas/:id
DELETE /admin/personas/:id

Persona KB Bindings

A Persona can have Knowledge Bases bound to it. When a channel uses that Persona, the bound KBs are automatically scoped into kb_search tool calls. Users never see or manage the underlying KBs directly — they talk to the Persona.

Get bindings:

GET /personas/:id/knowledge-bases                → { "data": [KB objects] }
GET /teams/:teamId/personas/:id/knowledge-bases  → { "data": [...] }
GET /admin/personas/:id/knowledge-bases          → { "data": [...] }

Set bindings (replace all):

PUT /personas/:id/knowledge-bases
PUT /teams/:teamId/personas/:id/knowledge-bases
PUT /admin/personas/:id/knowledge-bases
{
  "kb_ids": ["kb-uuid-1", "kb-uuid-2"],
  "auto_search": {
    "kb-uuid-1": true,
    "kb-uuid-2": false
  }
}

auto_search: when true, the KB is always searched (prepended to context). When false, it's available via the kb_search tool but not auto-injected.

Persona Avatars

POST   /personas/:id/avatar          ← multipart/form-data (field: "avatar")
DELETE /personas/:id/avatar
POST   /admin/personas/:id/avatar
DELETE /admin/personas/:id/avatar

Persona Tool Grants

Control which tools a persona can use during completions. The completion handler applies tool grants as a second-pass allowlist.

GET /personas/:id/tool-grants        → { "grants": ["web_search", "kb_search", ...] }
PUT /personas/:id/tool-grants        ← { "tool_ids": ["web_search", "calculator"] }

Admin equivalents:

GET /admin/personas/:id/tool-grants
PUT /admin/personas/:id/tool-grants

When a workflow version is published, persona tool grants at that moment are frozen into the version snapshot.

Persona Groups

Saved roster templates. A persona group is a named set of personas that can be stamped onto new conversations.

GET    /persona-groups               → { "data": [...] }
POST   /persona-groups               ← { "name", "description", "scope", "team_id" }
GET    /persona-groups/:id           → group with members
PUT    /persona-groups/:id           ← partial update
DELETE /persona-groups/:id

Members:

POST   /persona-groups/:id/members        ← { "persona_id", "is_leader": false, "sort_order": 0 }
DELETE /persona-groups/:id/members/:memberId

is_leader: the leader persona responds when no @mention is present in a group channel. Only one leader per group.

Persona Group Object:

{
  "id": "uuid",
  "name": "Support Team",
  "description": "...",
  "owner_id": "uuid",
  "scope": "personal|team|global",
  "team_id": "uuid|null",
  "members": [
    { "id": "uuid", "persona_id": "uuid", "is_leader": true, "sort_order": 0 }
  ],
  "created_at": "...",
  "updated_at": "..."
}

Resource Grants

See teams.md §15.3 for the grant system. Personas use grants to control who can see and use them beyond their base scope.