import { StreamChat } from "stream-chat";
const client = StreamChat.getInstance("<API_KEY>", "<API_SECRET>");
const { user_group } = await client.createUserGroup({
name: "Support Team",
description: "Frontline support agents",
member_ids: ["amy", "ben", "carol"],
});
await client.searchUserGroups({ query: "supp", limit: 10 }); // powers `@` autocomplete
await client.updateUserGroup("support-team", { name: "Customer Support" });
await client.addUserGroupMembers("support-team", { member_ids: ["dan"] });
await client.removeUserGroupMembers("support-team", { member_ids: ["dan"] });
await client.deleteUserGroup("support-team");Mentions
Introduction
Mentions let people tag a recipient inside a message by typing @. The React SDK supports five mention types across both ends of the flow — the composer surfaces them as autocomplete suggestions, and the message list highlights them in rendered text:
| Type | Token | Notifies | Message field |
|---|---|---|---|
user | @<name> | A single user | mentioned_users |
channel | @channel | Everyone in the channel | mentioned_channel |
here | @here | Members currently online | mentioned_here |
role | @<role> | Users with that role | mentioned_roles |
user_group | @<group> | Members of a named user group | mentioned_group_ids (send) / mentioned_groups (read) |
This guide walks through the whole feature. For deeper customization, it links out to the composer and message-rendering reference pages.
Enabling Mention Types
User mentions always work. The broadcast (@channel, @here), role, and user-group variants are gated by channel capabilities, so they only appear once the matching permission is granted to the sender's role.
| Mention type | Channel capability | Dashboard permission |
|---|---|---|
channel | notify-channel | NotifyChannel |
here | notify-here | NotifyHere |
role | notify-role | NotifyRole |
user_group | notify-group | NotifyGroup |
Grant these in the Stream Dashboard under Chat Messaging → Roles & Permissions: pick the role (for example channel_member) and the channel-type scope (for example messaging), then enable the relevant permissions. They surface on the channel as channel.data.own_capabilities and are checked at query time, so suggestions update if capabilities change. Until a capability is present, that mention type is filtered out of the suggestion list.
Two extra requirements:
- Role mentions resolve against the roles defined under the same Roles & Permissions dashboard page.
- User-group mentions require user groups to exist in your app — see User Groups below.
Mentioning in the Composer
Typing @ in the composer opens the autocomplete suggestion list. Suggestions are produced by MentionsSearchSource, which combines channel members (or all app users), the enabled broadcast/role variants, and matching user groups. Selecting a suggestion inserts the mention token into the text and tracks a typed mention entity on the TextComposer; on send, those entities are mapped onto the message fields listed above.
To customize the suggestion UI — replacing rows per mention type, wrapping the list, or filtering/transliterating results — see:
- Autocomplete Suggestions — customizing suggestion rows (including the dedicated
UserItem,BroadcastMentionItem,RoleItem, andUserGroupItem). - MessageComposer Middleware — customizing
MentionsSearchSource(filtering, transliteration, suggestion factory mappers).
User Groups
User groups are named, reusable sets of users that can be mentioned as a single unit with @<group name>. They are managed through the low-level stream-chat client and are independent of channel membership: the same group can be mentioned in any channel where group mentions are enabled.
For the complete API — endpoints, parameters, response objects, limits, and permissions — see the User Groups API reference. Because creating, updating, deleting, and changing membership are administrative operations, run them with a server-side token rather than from an end-user session.
Paginating Groups
UserGroupPaginator wraps queryUserGroups with cursor-based, forward-only pagination (the listing endpoint does not expose a backward cursor). Set teamId to scope the listing to a single team; changing it resets the paginator state.
import { StreamChat, UserGroupPaginator } from "stream-chat";
const client = StreamChat.getInstance("<API_KEY>");
const paginator = new UserGroupPaginator(client, { pageSize: 30 });
paginator.teamId = "acme"; // optional
await paginator.next(); // load the first page
const { items, hasNext } = paginator.state.getLatestValue();
if (hasNext) {
await paginator.next(); // load the next page
}Rendering Mentions in Messages
In the message list, every mention is rendered as a styled <span class="str-chat__message-mention"> carrying data-mention-type, data-mention-id, and (for user mentions) data-user-id. This lets you color each type with CSS or replace the rendering entirely with a custom component.
- renderText function — styling tokens per mention type and overriding the
mentionrenderer vianode.mentionedEntity. - Mentions Actions — reacting to clicks and hovers; non-user mention metadata is read from the message (
mentioned_channel,mentioned_here,mentioned_roles,mentioned_groups).