Feature Request
Telegram's groupPolicy is channel-wide ("open" or "mention"), so a single bot serving a busy supergroup has one behavior everywhere. With forum topics, that becomes a real limitation: a team group usually wants the bot to take part in project topics, but stay silent in announcement/tracking topics — and today that is impossible, because the policy applies to the whole chat at once.
Napcat already solved the equivalent problem per group, so this looks like a gap in Telegram rather than an intentional difference:
# 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)This request is to bring that same capability to Telegram, adapted to its topic model.
The Telegram-specific wrinkle
Telegram forum topics do not have their own chat id. Every topic in a supergroup shares the parent chat_id and is distinguished only by message_thread_id. So a group-scoped key like Napcat's str(group_id) cannot express "one topic". The key needs both parts.
Proposed Design
1. Config overrides
{
"channels": {
"telegram": {
"groupPolicy": "open",
"groupPolicyOverrides": {
"-1001668715626": "open",
"-1001668715626:7819": "mention"
}
}
}
}"<chat_id>"— applies to a whole chat."<chat_id>:<thread_id>"— applies to one forum topic; most specific match wins.- Unlisted scopes fall back to
groupPolicy.
This needs no new enum value: with the channel policy at "open", giving a topic "mention" already means "don't jump into the conversation, but answer if called" — which is exactly the usual intent for a muted topic. Keeping the value set at {mention, open} keeps the change small.
2. Manage it from chat
Editing JSON and restarting the gateway is a poor fit for "this topic is noisy right now". A command makes it self-service from the chat where the problem is:
/group → show the effective policy for this chat/topic
/group mention → only reply here when mentioned
/group open → reply to every message here
/group reset → clear the override for this chat/topicThe command is scoped to the calling chat/topic, so it never needs a raw thread id from the user.
Runtime overrides should layer on top of the static config rather than replace it, so durable policy can stay in config.json while /group handles exceptions:
- runtime topic override
- runtime chat override
- static topic override (
config.json) - static chat override (
config.json) - channel-wide
groupPolicy
Scopes should be keyed by channel too (telegram:<chat_id>[:<thread_id>]), so Telegram and Discord overrides cannot collide.
Suggested Scope
Two PRs, since they are independently useful and reviewable:
groupPolicyOverridesconfig support + Telegram resolution.- The
/groupcommand backed by a small runtime store, layering over (1).
A PR for (1) is up as #5972. I have (2) ready to open on top of it.
Alternatives Considered
- Reusing
allowFrom/groupAllowFrom: those gate who may talk, not when the bot answers. Slack'sgroupRequireMentionis closer but still not per-scope. - Making the topic list an allowlist-only feature (
groupPolicy: "allowlist"): would need a new policy value and still could not express "open here, mention there, in one chat". - Editing
config.jsonfrom the command: nanobot refreshes agent runtime config on file change, but channels read their config at construction, so it would not take effect without a restart. A separate runtime store avoids that coupling.
Environment
- nanobot
0.3.5(main@3cf6ed6) - Use case: team Telegram supergroup with per-topic behavior
Activity
0No activity yet.