Skip to content

Refactor: Extract bot-turn throttling from message() into resolve/record/evaluate/execute pipeline #531

@chaodu-agent

Description

@chaodu-agent

Motivation

Bot turn counting, channel gating, warning emission, and business logic are all mixed in message(). This caused #529 (warning sent to non-allowed channels) and makes #530 (dedup) hard to fix cleanly.

Both Discord and Slack adapters have this problem. The warning-before-gating pattern exists in both discord.rs and slack.rs.

Proposed Architecture

message() arrives
  → resolve_context()           // build ResolvedMessageContext (shared, cross-adapter)
  → record_turns()              // pure counting, no side effects (#483 invariant)
  → evaluate_gating()           // channel/user/bot permission check
  → evaluate_throttle_effects() // decide: Continue | Stop | StopWithEffect(Warning)
  → execute_effects()           // single place for side effects (say, react, etc.)
  → dispatch_business_logic()   // handle_message, streaming, etc.

Design Requirements

  1. Shared ResolvedMessageContextchannel_id, parent_id, is_bot, allowed_here, etc. computed once, shared across all stages. No duplicate resolution.

  2. Decisions, not side effects — each stage returns a decision enum (Continue, Stop, StopWithEffect(Effect::Warning(...))). Side effects executed by a single coordinator, not inside the stage.

  3. Throttle state abstracted behind store/policy — don't let stages directly operate on HashMap. Enables Bug: Multiple allowed bots each post their own turn limit warning in the same thread #530 dedup and future shared state without re-splitting.

  4. Counting before gating, emission after gating — the key insight: counting and emission must be decoupled. Counting runs early (all bot messages), emission runs after gating (only allowed channels).

  5. Cross-adapter design — the pipeline must apply to both Discord (discord.rs) and Slack (slack.rs). Both have the same warning-before-gating bug pattern today.

Affected Code

  • discord.rs line ~258-290: bot turn counting + warning say() before channel gating
  • slack.rs line ~678-697: same pattern — classify_bot_message + send_message before allow_bot_messages gating

Incremental Rollout

  1. ✅ PR fix: gate bot turn warning behind allowed_channels check #528 — hotfix for Discord gating correctness (merge first)
  2. Extract resolve_message_context() and evaluate_turn_policy() as minimal first step (both adapters)
  3. Full pipeline refactor
  4. Bug: Multiple allowed bots each post their own turn limit warning in the same thread #530 dedup solved naturally in the throttle evaluation layer

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions