Skip to content

Require an @-mention to respond in group rooms (leave 1:1 rooms unchanged) #72

Description

@pinpox

Summary

In rooms with more than two members, opencrow should only respond when it is
explicitly mentioned (e.g. @opencrow_one). In 1:1 rooms (just the bot and one
other user) the behaviour stays exactly as today: respond to every allowed
message.

Motivation

The Matrix backend currently answers every message from an allowed sender,
regardless of room size and with no addressing. This is fine for a 1:1 bot but
breaks down in shared rooms:

  • Multiple opencrow instances in the same room all reply to every message — N
    answers per prompt and N concurrent LLM calls.
  • Even a single bot in a human group chat is noisy: it replies to messages that
    were not meant for it.

Requiring an explicit mention in group rooms makes bots addressable and quiet by
default, while keeping the frictionless 1:1 experience.

Current behaviour

matrix/backend.go filterMessage drops a message only when: not initial-synced,
the sender is the bot itself, the sender is not in the allowlist, or the msgtype
isn't text/media. There is no room-size or mention check — every remaining message
reaches b.handler and gets a reply.

Desired behaviour

  • 1:1 room (exactly 2 joined members: the bot + one other): unchanged —
    respond to all allowed messages.
  • Group room (>2 joined members): respond only if the message explicitly
    addresses this bot.

"Addresses this bot" should mean any of:

  • An intentional mention: m.mentions.user_ids contains the bot's own MXID — the
    robust, spec-compliant signal (mautrix exposes this as
    event.MessageEventContent.Mentions).
  • (Optional) a reply (m.in_reply_to) to one of the bot's own messages.
  • (Optional fallback) body / formatted_body contains the bot's localpart or a
    matrix.to pill, for clients that don't emit m.mentions.

When the bot does respond, the mention token should be stripped from the text sent
to the model so the prompt isn't polluted with @opencrow_one.

Implementation sketch

  • Add the gate in filterMessage (or right after, where the room is known):
    • Determine the joined-member count for evt.RoomID (e.g. via
      Client.JoinedMembers, cached / derived from sync state rather than a request
      per message).
    • members <= 2 → keep current behaviour.
    • members > 2 → require the bot's MXID (b.userID) in the message's
      m.mentions.user_ids, otherwise drop.
  • Consider a config flag (e.g. OPENCROW_MATRIX_REQUIRE_MENTION_IN_GROUPS,
    default true) so it can be disabled.

Edge cases / notes

  • "1:1" = exactly 2 joined members; ignore invited/left state.
  • A room with one human + two bots counts as a group, so each bot replies only
    when its own MXID is mentioned — this is the intended multi-bot UX.
  • Encrypted rooms: mention detection runs on decrypted content, so it works the
    same way.
  • Member count must track join/leave (membership events already flow through the
    syncer).
  • Prefer m.mentions over display-name matching (the latter is ambiguous).

Acceptance criteria

  • In a 2-member room, the bot replies to allowed messages with no mention
    (unchanged).
  • In a >2-member room, the bot replies only to allowed messages that mention its
    MXID; unaddressed messages are ignored.
  • With multiple bots in one room, mentioning @opencrow_one triggers only
    opencrow_one.
  • The mention token is not included in the text sent to the model.
  • (If added) the config flag toggles the group-room requirement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions