Problem
groupPolicy is channel-wide on Matrix (one of open, mention, allowlist applies to every group room). Only DMs (≤2 members) bypass it (_should_process_message, nanobot/channels/matrix/runtime.py, v0.3.5).
A deployment with many rooms usually wants different behavior per room:
| Room type | Desired policy | Why |
|---|---|---|
| Topic/project rooms | open — respond to every message | Bot is the copilot there |
| Shared / busy room | mention — respond only when @mentioned or replied to | Unprompted replies are noise, and the room will also host another bot |
This cannot be expressed today: open everywhere is noisy in the shared room, mention everywhere silences the topic rooms.
Existing precedent in the codebase
The Napcat channel already ships this exact mechanism — the ask is a small parity port to Matrix:
nanobot/channels/napcat/manifest.py:"groupPolicyOverrides": field("json", default={})nanobot/channels/napcat/runtime.py:group_policy_overrides: dict[str, GroupPolicy] = Field(default_factory=dict) policy = self.config.group_policy_overrides.get(str(group_id), self.config.group_policy)
Related Telegram-side RFCs with the same gap: #3309, #5972.
Proposed config
{
"channels": {
"matrix": {
"groupPolicy": "open",
"groupPolicyOverrides": {
"!aaaa...:example.org": "mention"
}
}
}
}- Keys: Matrix room IDs. Values: the same vocabulary as Matrix's
groupPolicy—"open" | "mention" | "allowlist"(Napcat additionally accepts a probability float; not required here). - Precedence: per-room override → channel
groupPolicy. Rooms not listed behave exactly as today, so existing configs are unaffected. - An
"allowlist"override would reuse the existing channel-widegroupAllowFromlist for that room (minimal change; per-room allow lists could come later). allowRoomMentionssemantics unchanged.
Implementation
Single lookup change at the existing policy-resolution point in nanobot/channels/matrix/runtime.py, _should_process_message() (~L1136–1149 in v0.3.5):
- policy = self.config.group_policy
+ policy = self.config.group_policy_overrides.get(room.room_id, self.config.group_policy)plus the matching field("json", default={}) declaration in channels/matrix/manifest.py, mirroring Napcat.
Happy to attempt the PR if this is wanted.
Activity
0No activity yet.