Skip to main content

Channels

Channels bring team conversations into Libre WebUI: public and private rooms plus direct messages, with threads, reactions, pins, unread tracking, file attachments, and @model replies — all on the same durable, encrypted foundations as chat.

Channel types and membership​

TypeWho can see itWho joins
publicEveryone can browse itAnyone joins themselves
privateMembers onlyThe owner invites members
dmThe two participants onlyOpened automatically; always exactly two

Membership is the only authority over channel content: every read and write — including attachment downloads and live event delivery — checks the caller's membership first, and non-members receive a non-enumerating 404. The global administrator role deliberately confers no access to channel content.

The creator of a public or private channel is its owner. Owners rename, archive, invite (private), remove members, moderate messages, and delete the channel; an owner leaves by deleting the channel, never by abandoning it. Direct messages are deduplicated per pair: opening a DM with the same person always lands in the same conversation.

The timeline​

Messages form a persistent, ordered timeline that is read with keyset cursors (created_at plus message id) in either direction, so paging never skips or duplicates entries.

  • Idempotent posts. The client supplies the message identity; a retried request lands on the same timeline entry exactly once.
  • Tombstoned deletion. Deleting a message clears its content but keeps the timeline entry, so threads never dangle and ordering never shifts. Authors delete their own messages; channel owners may moderate any.
  • Edits are author-only and carry an editedAt marker.
  • Threads are one level deep. Any root message can host a thread; replies to replies are rejected. Root messages carry live reply counts.
  • Reactions are per-user per-emoji, counted without duplicates.
  • Pins are member-curated and listed per channel.

Channel names, descriptions, and message content are encrypted at rest with the same boundary as chat messages.

Unread state​

Each membership carries a monotonic read cursor. Unread counts are computed server-side per channel (your own messages are never unread) and POST /api/channels/:channelId/read advances the cursor — it never moves backwards, so a stale client cannot resurrect read messages.

Real-time delivery​

Every timeline mutation is appended to the durable event stream channel:<id> and fans out over GET /api/channels/:channelId/events (SSE). Membership is re-checked before every delivery, so removing a member fails their live stream closed. The SQL timeline remains authoritative: a subscriber that missed events simply re-reads the timeline — the ledger is delivery, not truth.

Attachments​

Files upload first (POST /api/channels/:channelId/attachments), park briefly in a shared claim cache, and attach when the message posts; an upload claim is single-use and expires unclaimed after 15 minutes. Blob bytes belong to the uploader (their quota), and downloads re-check channel membership on every request.

@model replies​

The composer can direct a message at a model. The reply appears immediately as a pending model-authored message and completes through a durable job that runs strictly under the invoking member's identity: their model access, their provider credentials, their routing — never the channel owner's or another member's. A member who is removed while a mention is queued cannot keep it alive: the job re-checks membership before generating and records a visible failure instead. Model failures surface on the reply itself rather than disappearing into a queue.

A mention also reaches the mentioned member by email when they turned on Channel mentions under Settings → Notifications and an administrator has set up the outgoing mail server (see Notifications).

Model replies use the recent channel conversation (up to 30 messages) as context.

Chat tools are wired in: when the mentioning member passes the tools feature gate and has a non-empty catalog, the reply runs the same multi-round tool loop a chat turn runs, against that member's own visible tool servers and builtins. A channel binds no persona, so no persona tool binding narrows the catalog.

Nobody is watching a mention the way someone watches a chat, so a side-effecting tool call is declined outright unless the member already holds a standing approval for it. The reply says so, and the model is told to run it from a chat instead. Read-only tools run without asking, exactly as they do in chat. Standing approvals are scoped per channel: an "allow for this chat" decision never carries into a channel, and a per-channel approval never leaks into another channel or into chat. Because only read-only work can run unattended, a retried mention job is safe to repeat.

The reply carries a bounded summary of the calls it made (at most 12, with truncated arguments and result previews), shown as a "Tools used" disclosure under the message. Knowledge retrieval and web search are still not wired into channel mentions.

Limits​

LimitValue
Channels created per user50
Members per channel200
Messages per channel50,000
Message length8,000 characters
Attachments per message5 × 10 MB
Reactions per message200

Boundaries​

  • Presence indicators and typing state are not implemented.
  • Channel content export and retention policies follow the instance backup story; there is no per-channel export yet.
  • Mentions notify through the in-app notification service; there is no per-channel notification preference yet beyond leaving the channel.