Skip to content

Make proactive channel-message rate limits configurable (Slack/Telegram/DM guardrails) #1609

Description

@vybe

Summary

The proactive channel-messaging rate limits (10 messages/hour/channel, 100 messages/hour/agent for Slack and Telegram; 10 messages/hour/recipient for proactive DMs) are hardcoded module constants. They were introduced as anti-spam guardrails (#349, #350, #321), but they cannot be tuned, which blocks legitimate high-volume autonomous use cases — e.g. an agent that posts a Slack message for each inbound support request. Make them admin-configurable with the current values as defaults.

Context

A community report hit these caps building an autonomous Slack-posting agent and asked whether they are configurable (they are not) and whether the enterprise edition lifts them (it does not — they are OSS guardrails, not entitlement gates).

The hardcoded constants:

  • src/backend/routers/slack.py_SLACK_PROACTIVE_PER_CHANNEL = 10, _SLACK_PROACTIVE_PER_AGENT = 100 (gates POST /api/agents/{name}/slack/channels/{channel_id}/messages, backing MCP send_group_message)
  • src/backend/routers/telegram.py_PROACTIVE_RATE_LIMIT_PER_GROUP = 10, _PROACTIVE_RATE_LIMIT_PER_AGENT = 100 (same caps, bespoke in-memory bucket)
  • src/backend/services/proactive_message_service.pyRATE_LIMIT_MAX_PER_HOUR = 10 per agent-recipient pair (backing MCP send_message)

The codebase already has the pattern to follow: the inbound channel limiter reads channel_rate_limit_max / channel_rate_limit_window from settings_service with hardcoded fallbacks (src/backend/adapters/message_router.py), and max_parallel_tasks_ceiling (#506) established the admin-tunable-guardrail shape (runtime-resolved from system_settings, range-validated, no per-process cache so --workers 2 stays consistent, no migration needed).

Note: replies to inbound Slack/Telegram messages (DM/@mention/thread via the channel adapter) are NOT gated by these caps — only agent-initiated proactive sends are. That distinction should land in the docs as part of this issue.

Acceptance Criteria

  • The three proactive cap families (Slack per-channel/per-agent, Telegram per-group/per-agent, proactive-DM per-recipient) are admin-configurable, read at request time via settings_service (no restart required, --workers 2-consistent)
  • Current values (10/100/10 per hour) remain the defaults — existing deployments see zero behavior change
  • Values are range-validated with a named 400/422 error on bad input; a decision is made and documented on whether 0 = disabled is allowed (if so, it warns) or a floor is enforced
  • Telegram's bespoke in-memory bucket migrates to the shared sliding-window limiter (src/backend/services/rate_limiter.py, refactor(backend): unified Redis sliding-window rate limiter (replace ad-hoc per-endpoint limiters) #1023), matching what Slack already uses (also fixes multi-worker inconsistency of the in-memory buckets)
  • Settings are surfaced in the admin Settings UI (not .env-only), with honest display of current effective values
  • 429 responses keep a clear, actionable message naming which cap fired
  • Settings changes are audit-logged (mirrors other admin settings)
  • Docs updated: requirements area file + user docs note that proactive caps are configurable and that inbound replies are not subject to them

Technical Notes

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions