Stream Feeds

Integrating moderation in Activity Feeds is straightforward and requires minimal code changes. Once you configure a moderation policy, Stream automatically moderates activities and comments as they are created or updated. This guide walks you through setting up moderation and monitoring flagged content.

Configure Moderation Policy

A moderation policy defines how content should be moderated. You can configure your policy through the dashboard or via the API. Activity and comment custom is included in the moderation payload, so content custom-property rules match Feeds the same way they match Chat.

For Feeds v3, Stream picks a policy in this order:

  1. feed.custom.moderation_policy -- if that exact config exists
  2. feeds:{group_id}:{feed_id} -- individual feed
  3. feeds:{group_id} -- feed group
  4. feeds -- app-wide default

If custom.moderation_policy is missing, empty, or names a config that does not exist, Stream continues with the feeds:... keys. Activity or comment custom.moderation_policy is ignored for this assignment.

To set up an app-wide policy for all feeds content:

client.moderation().upsertConfig(UpsertConfigRequest.builder()
    .key("feeds")
    .aiTextConfig(AITextConfig.builder()
        .rules(List.of(
            BodyguardRule.builder().label("SPAM").action("flag").build(),
            BodyguardRule.builder().label("HATRED").action("remove").build()
        )).build())
    .blockListConfig(BlockListConfig.builder()
        .rules(List.of(BlockListRule.builder().name("profanity_en").action("remove").build()))
        .build())
    .aiImageConfig(AIImageConfig.builder()
        .rules(List.of(AWSRekognitionRule.builder().label("Non-Explicit Nudity").action("flag").build()))
        .build())
    .build()).execute();

You can also configure policies per feed group (e.g., feeds:user for user feeds, feeds:timeline for timeline feeds) to apply different moderation rules to different feed types.

Assign a named policy to a feed

To share one policy across many feeds without cloning feed groups, upsert a config under any key (for example pm:acme) and set that key on each feed. The field is writable on create and update.

feed.update(UpdateFeedRequest.builder()
    .custom(Map.of("moderation_policy", "pm:acme"))
    .build());

Auto-Moderation on Activities

Once the policy is configured, activities are automatically moderated when created or updated. No additional code is needed -- just add activities as you normally would.

Server-side requests skip moderation by default. Set force_moderation: true to moderate an activity or comment created from your backend.

Warning:

force_moderation is server-side only and ignored when sent from a client-side SDK.

When an activity contains content that violates your policy, Stream takes the configured action:

  • remove -- the activity is removed and appears in the review queue
  • flag -- the activity is published but flagged for review
  • bounce -- the activity is rejected entirely and not saved
  • shadow -- the activity is hidden from other users but visible to the creator
  • mask_flag (blocklists only) -- blocklisted words in the text are replaced with asterisks, and the activity is published and flagged for review. See Mask Sensitive Content
  • mask (blocklists only) -- blocklisted words in the text are replaced with asterisks, without flagging

The API response includes a moderation object with details about the action taken:

{
  "id": "activity-123",
  "type": "post",
  "text": "the activity text",
  "moderation": {
    "action": "remove",
    "original_text": "the activity text",
    "text_harms": ["HATRED"],
    "blocklists_matched": ["profanity_en"]
  }
}

Feeds returns ModerationV2Response. It does not include status or recommended_action.

Field Type Description
action string keep, flag, remove, shadow, bounce, bounce_flag, bounce_remove, mask, or mask_flag
original_text string Text before masking
text_harms string[] NLP or LLM labels, such as HATRED or SPAM
image_harms string[] Image labels, such as Explicit
blocklists_matched string[] Blocklists that matched

Auto-Moderation on Comments

Comments are also automatically moderated using the same policy. When a user adds a comment, Stream checks the content and applies the configured action.

If a comment is removed, other users do not see it. The response includes the moderation action:

{
  "id": "comment-789",
  "text": "...",
  "moderation": {
    "action": "remove",
    "original_text": "...",
    "text_harms": ["HATRED"]
  }
}
Info:

Reactions (likes, etc.) are not auto-moderated, only activities and comments.

Policy keys

Feeds looks up feeds:{group} and feeds:{group}:{id}. Set custom.moderation_policy on a feed to name an exact policy instead. Poll text uses polls:default.

User-Driven Actions

In addition to automated moderation, users can flag content or other users for review.

Flag a User

client.moderation().flag(FlagRequest.builder()
    .entityType("stream:user")
    .entityID(targetUserId)
    .reason("harassment")
    .userID(reportingUserId)
    .build()).execute();

Ban a User

client.moderation().ban(BanRequest.builder()
    .targetUserID(targetUserId)
    .bannedByID(moderatorId)
    .reason("Repeated violations")
    .build()).execute();

Banned users are prevented from reading feeds and creating activities or reactions.