---
title: Channel Invitations (per-channel roles + who-can-post, in Team Chat)
---

# Channel Invitations (per-channel roles + who-can-post, in Team Chat)

## What it is

In **Team Chat**, a channel isn't automatically open to everyone in your workspace — you choose who's
in it, what each person can do, and who's allowed to post. Every channel member has one of three
roles (**Manager**, **Member**, or **Read-only**), and a channel can be set so that **everyone** may
post or **only managers** may. It's the Slack-style "invite people to a channel, give them a role"
model, built into Omniscio.

## Where to find it

Everything on this page lives inside a channel in **Team Chat**, in the **Members** panel that
slides in down the right-hand side — there is no separate settings page for it. You reach that
panel from the channel itself, so open the channel first and look at its header.

### Where it lives

Open any channel and click the **member count** at the top (e.g. "5 members"). That opens the
**Members** panel down the right side, listing everyone in the channel with their role.

- **Add someone:** in the Members panel, click **Add members** (the person-plus button). A dialog —
  *"Add members to #channel-name"* — lets you search your workspace and pick people. You can add up
  to **50 people at once** and choose whether each joins as a **Member** or **Read-only**. Adding is
  instant (Slack-style): there's no invite-accept step — the person is in the channel right away, and
  a small system line (*"Alex added Sam to the channel"*) records it.
- **Change a role or remove someone:** each row in the Members panel has the controls to change a
  person's role or take them out of the channel.

The management controls (add / change role / remove) appear only for people who can use them — a
**workspace admin** or a **channel Manager**. Everyone else sees the member list read-only.

## How it behaves

### The three roles

- **Manager** — full control of the channel. Can post, add and remove members, change other people's
  roles, and change the channel's settings (including who can post). A channel always keeps at least
  one manager — you can't remove or demote the last one.
- **Member** — the everyday role. Can read everything and post messages and replies, but can't manage
  members or settings. This is the default role when someone joins an open channel.
- **Read-only** — can read the whole channel and add reactions, but **can't post**. In place of the
  message box they see a small banner: *"You have read-only access to this channel."*

### Who can post

A channel manager or workspace admin can open the channel's **Edit** dialog and set **Who can post**:

- **Everyone** (the default) — every member can post, except Read-only members, who never post.
- **Managers only** — only managers can post. Everyone else can still read and react, but their
  message box is replaced by a banner: *"Only managers can post in this channel."*

### Turning it on

Channel Invitations is a shipped feature — it's on by default, so the Members panel, roles, and
who-can-post control are simply present in Team Chat. (Team Chat itself is the container: if you don't
see channels at all, Team Chat may still need enabling in **Settings → Lab**.) The developer/QA flag
`AMC_SHOW_CHANNEL_INVITATIONS=1` and the `channelInvitationsEnabled` setting also force it on.

## For agents

### Under the hood

- Roles live in a Firestore subcollection: `…/channels/{channelId}/channelMembers/{uid}` holds
  `{ uid, role, addedBy, addedAt }`, and the channel doc keeps a denormalized `memberUids` index plus
  a `postingPermission` field (`'everyone'` | `'managers-only'`). Pre-feature members with no
  subcollection doc are lazily backfilled as `'member'`.
- The read-only / managers-only composer swap is decided by `resolveComposerReadOnly()`, which renders
  the `ReadOnlyBar` in place of the composer. Enforcement is ALSO in `firebase/firestore.rules` (a
  client can't post by faking a role) — the rules ship separately from the app build.
- UI: `ChannelMembersPanel.tsx`, `AddChannelMembersDialog.tsx` (bulk cap 50), and the **Who can post**
  select in `EditChannelDialog.tsx` (admin-only, feature-gated via
  `isUnreleasedFeatureVisibleInRenderer('channel-invitations', settings)`). Invariants — no DM
  members, last-manager protection, single-batch atomic writes — are locked by the contract
  `team-chat-channel-invitations-contract`.
- Desktop/PWA render the management UI; the Firestore rules apply uniformly to every client. Setting:
  `channelInvitationsEnabled`. Feature id: `channel-invitations`.

## Related

Team Chat itself — channels, messages, and how the workspace is organised — is on the
[Team Chat](team-chat.md) page, and the sidebar row that gets you there is described on the
[Communication group](communication.md) page. If what you are after is messaging a specific agent
rather than a person in a channel, that is a different surface, covered on the
[cross-session messaging](cross-session-messaging.md) page.
