Problem
The FAQ promises bundled Slack and Discord adapters for v0.2. Unlike the HTTP / OpenAI / Anthropic adapters, Slack and Discord bots are event-driven: you post a message to a channel and the bot replies asynchronously. The ChatbotAdapter.send_message(prompt) -> ChatbotResponse contract is synchronous, so each adapter must post a message and then wait for the bot-under-test's reply (filtered by author id) in that channel/thread, with a timeout.
An OpenAI Assistants adapter was also considered — skip it. The Assistants API is deprecated with an Aug 26 2026 sunset; a new adapter would be dead code. The existing [openai] adapter (Chat Completions / Responses) is the right surface; extend it if stateful threads are needed.
Proposed approach
adapters/slack_chat.py — SlackChatbotAdapter + AsyncSlackChatbotAdapter, [slack] extra (slack-sdk>=3.40). WebClient only (no Bolt / Socket Mode / event loop). send_message: chat_postMessage → poll conversations_replies(oldest=sent_ts), filter for the bot's user/bot id. Exponential backoff (first sleep ~3s, cap ~8s) to respect the non-Marketplace 1 req/min cap on conversations.replies. session_id → a thread anchored on the first message's ts; reset_session drops it.
adapters/discord_chat.py — DiscordChatbotAdapter + AsyncDiscordChatbotAdapter, [discord] extra (discord.py>=2.7). REST polling (GET /channels/{id}/messages?after={sent_id}) — avoids a persistent gateway connection and the MESSAGE_CONTENT privileged intent. Filter for author.id == bot_user_id.
- Common: lazy import + install hint; constructor
channel_id, bot_user_id, token from env, timeout_s=30, poll_interval_s, reply_strategy: "first" | "concat" (for multi-message replies); redact the token from raw; raise WardenBotInfraError on API error / timeout (never AssertionError).
- Tests mock the HTTP layer (
respx) — no real workspace needed in CI; live tests behind an env-var guard.
- Separate
[slack] / [discord] extras (don't force both).
Acceptance criteria
References
Complexity: needs-maintainer (Slack rate-limit polling strategy + HTTP-mock test pattern).
Problem
The FAQ promises bundled Slack and Discord adapters for v0.2. Unlike the HTTP / OpenAI / Anthropic adapters, Slack and Discord bots are event-driven: you post a message to a channel and the bot replies asynchronously. The
ChatbotAdapter.send_message(prompt) -> ChatbotResponsecontract is synchronous, so each adapter must post a message and then wait for the bot-under-test's reply (filtered by author id) in that channel/thread, with a timeout.Proposed approach
adapters/slack_chat.py—SlackChatbotAdapter+AsyncSlackChatbotAdapter,[slack]extra (slack-sdk>=3.40).WebClientonly (no Bolt / Socket Mode / event loop).send_message:chat_postMessage→ pollconversations_replies(oldest=sent_ts), filter for the bot's user/bot id. Exponential backoff (first sleep ~3s, cap ~8s) to respect the non-Marketplace 1 req/min cap onconversations.replies.session_id→ a thread anchored on the first message'sts;reset_sessiondrops it.adapters/discord_chat.py—DiscordChatbotAdapter+AsyncDiscordChatbotAdapter,[discord]extra (discord.py>=2.7). REST polling (GET /channels/{id}/messages?after={sent_id}) — avoids a persistent gateway connection and theMESSAGE_CONTENTprivileged intent. Filter forauthor.id == bot_user_id.channel_id,bot_user_id, token from env,timeout_s=30,poll_interval_s,reply_strategy: "first" | "concat"(for multi-message replies); redact the token fromraw; raiseWardenBotInfraErroron API error / timeout (neverAssertionError).respx) — no real workspace needed in CI; live tests behind an env-var guard.[slack]/[discord]extras (don't force both).Acceptance criteria
SlackChatbotAdapter/AsyncSlackChatbotAdaptersatisfy the (async) Protocol;to_sync()round-trips.DiscordChatbotAdapter/AsyncDiscordChatbotAdaptersatisfy the (async) Protocol.ImportErrorwith install hint.reset_sessionstarts a fresh thread/conversation on the nextsend_message.WardenBotInfraError(notTimeoutError/AssertionError).ChatbotResponse.raw.conversations.repliescap (backoff; documented).[slack]/[discord]extras added; nothing added to the base install.bot_user_id, rate-limit notes); FAQ link updated.References
conversations.replies: https://docs.slack.dev/reference/methods/conversations.replies/Complexity: needs-maintainer (Slack rate-limit polling strategy + HTTP-mock test pattern).