|
| 1 | +# Assistant-Thread APIs |
| 2 | + |
| 3 | +## Scope |
| 4 | + |
| 5 | +Canonical local synthesis of the Slack and Chat SDK APIs this repository |
| 6 | +relies on for Slack assistant-thread lifecycle, status, and title behavior. |
| 7 | + |
| 8 | +Use this file before changing: |
| 9 | + |
| 10 | +- assistant-thread status/title behavior |
| 11 | +- DM versus channel-thread Slack context handling |
| 12 | +- assistant lifecycle event handling |
| 13 | +- Slack skill guidance that refers to `assistant.threads.*` |
| 14 | + |
| 15 | +This file intentionally separates: |
| 16 | + |
| 17 | +1. vendor-documented API facts |
| 18 | +2. repository policy layered on top |
| 19 | +3. concrete implementation seams in this repo |
| 20 | + |
| 21 | +## External API Surfaces We Rely On |
| 22 | + |
| 23 | +### Slack Events API |
| 24 | + |
| 25 | +1. `app_mention` |
| 26 | + |
| 27 | +- Used for explicit mentions in channels. |
| 28 | +- Carries `channel`, `ts`, and optional `thread_ts`. |
| 29 | +- Messages in direct messages are not delivered through `app_mention`. |
| 30 | + |
| 31 | +2. `message.im` |
| 32 | + |
| 33 | +- Used for DM traffic to the bot. |
| 34 | +- Carries `channel`, `ts`, and may omit `thread_ts` on the first DM message. |
| 35 | +- Slack AI/app-thread continuation in DMs depends on `thread_ts` when present. |
| 36 | + |
| 37 | +3. `assistant_thread_started` |
| 38 | + |
| 39 | +- Carries `assistant_thread.channel_id`, `assistant_thread.thread_ts`, and optional `assistant_thread.context.channel_id`. |
| 40 | +- Used to initialize suggested prompts and thread-title state for Slack assistant threads. |
| 41 | + |
| 42 | +4. `assistant_thread_context_changed` |
| 43 | + |
| 44 | +- Carries the same `assistant_thread.*` shape as the start event. |
| 45 | +- Used to refresh context without resetting an established conversation title. |
| 46 | + |
| 47 | +### Slack Web API |
| 48 | + |
| 49 | +1. `assistant.threads.setStatus` |
| 50 | + |
| 51 | +- Requires `channel_id` and `thread_ts`. |
| 52 | +- Slack clears status automatically when a reply is posted. |
| 53 | +- Sending an empty `status` clears the indicator explicitly. |
| 54 | +- Slack currently accepts either `chat:write` or `assistant:write` for this method. This changed in March 2026 and may change again, so re-check the live docs before changing scope guidance. |
| 55 | + |
| 56 | +2. `assistant.threads.setTitle` |
| 57 | + |
| 58 | +- Requires `channel_id`, `thread_ts`, and `title`. |
| 59 | +- Still documented as an assistant-thread/title API, primarily for app-thread history in DMs. |
| 60 | +- `assistant:write` remains the documented scope for this method. |
| 61 | + |
| 62 | +3. `assistant.threads.setSuggestedPrompts` |
| 63 | + |
| 64 | +- Requires `channel_id`, `thread_ts`, and prompt payloads. |
| 65 | +- Used from the lifecycle path when Slack starts or refreshes an assistant thread. |
| 66 | + |
| 67 | +### Chat SDK Slack Adapter |
| 68 | + |
| 69 | +1. `setAssistantStatus(channelId, threadTs, status, loadingMessages?)` |
| 70 | + |
| 71 | +- Thin adapter wrapper around Slack `assistant.threads.setStatus`. |
| 72 | + |
| 73 | +2. `setAssistantTitle(channelId, threadTs, title)` |
| 74 | + |
| 75 | +- Thin adapter wrapper around Slack `assistant.threads.setTitle`. |
| 76 | + |
| 77 | +3. `startTyping(threadId, status?)` |
| 78 | + |
| 79 | +- Available in the adapter, but this repository does not use it as the baseline visible Slack progress surface. |
| 80 | + |
| 81 | +## Repository Policy |
| 82 | + |
| 83 | +1. Assistant status is the primary in-flight progress surface. Visible reply text is finalized before posting. |
| 84 | +2. For non-DM message events, the live assistant-thread key is `channel + (thread_ts ?? ts)`. |
| 85 | +3. For `message.im`, assistant-thread status/title updates require an explicit live `thread_ts`. Do not synthesize DM assistant roots from generic `ts` or persisted state. |
| 86 | +4. For lifecycle events, use `assistant_thread.channel_id + assistant_thread.thread_ts`. |
| 87 | +5. Reply continuity and assistant-thread API eligibility are separate concerns. A persisted thread root can be valid for reply threading without being valid for `assistant.threads.*`. |
| 88 | +6. Conversation-specific thread titles are DM-only in the normal reply path and come from the earliest human message the runtime actually knows about for that thread. |
| 89 | +7. `assistant_thread_context_changed` may refresh prompts/context, but must not clobber an already established conversation title. |
| 90 | + |
| 91 | +## Implementation Map In This Repo |
| 92 | + |
| 93 | +1. Live assistant-thread context selection: |
| 94 | + |
| 95 | +- `packages/junior/src/chat/runtime/thread-context.ts` |
| 96 | +- `getAssistantThreadContext()` |
| 97 | + |
| 98 | +2. Status sending and token binding: |
| 99 | + |
| 100 | +- `packages/junior/src/chat/slack/assistant-thread/status-send.ts` |
| 101 | +- `packages/junior/src/chat/slack/assistant-thread/status.ts` |
| 102 | +- `packages/junior/src/chat/slack/assistant-thread/status-scheduler.ts` |
| 103 | + |
| 104 | +3. Lifecycle event handling: |
| 105 | + |
| 106 | +- `packages/junior/src/chat/slack/assistant-thread/lifecycle.ts` |
| 107 | +- `packages/junior/src/chat/runtime/slack-runtime.ts` |
| 108 | + |
| 109 | +4. DM title generation and permission handling: |
| 110 | + |
| 111 | +- `packages/junior/src/chat/slack/assistant-thread/title.ts` |
| 112 | + |
| 113 | +5. Current delivery contract: |
| 114 | + |
| 115 | +- `specs/slack-agent-delivery-spec.md` |
| 116 | + |
| 117 | +## Audit Checklist |
| 118 | + |
| 119 | +When changing code or guidance in this area, verify all of the following: |
| 120 | + |
| 121 | +1. `app_mention` handling does not treat channel traffic like `message.im`. |
| 122 | +2. Channel-thread first replies use the live `ts` when `thread_ts` is absent. |
| 123 | +3. DM status/title updates are skipped when the current `message.im` lacks explicit `thread_ts`. |
| 124 | +4. Lifecycle events use `assistant_thread.channel_id` and `assistant_thread.thread_ts`. |
| 125 | +5. `assistant.threads.setStatus` calls never receive adapter-scoped `slack:<channel>` IDs. |
| 126 | +6. Title generation stays best effort and does not block visible reply delivery. |
| 127 | +7. Skill/docs wording does not hardcode stale scope assumptions for `setStatus`. |
| 128 | + |
| 129 | +## Sources |
| 130 | + |
| 131 | +- Slack `app_mention`: https://docs.slack.dev/reference/events/app_mention/ |
| 132 | +- Slack `message.im`: https://docs.slack.dev/reference/events/message.im |
| 133 | +- Slack `assistant_thread_started`: https://docs.slack.dev/reference/events/assistant_thread_started |
| 134 | +- Slack `assistant_thread_context_changed`: https://docs.slack.dev/reference/events/assistant_thread_context_changed/ |
| 135 | +- Slack `assistant.threads.setStatus`: https://docs.slack.dev/reference/methods/assistant.threads.setStatus |
| 136 | +- Slack `assistant.threads.setTitle`: https://docs.slack.dev/reference/methods/assistant.threads.setTitle |
| 137 | +- Slack status scope update: https://docs.slack.dev/changelog/2026/03/05/set-status-scope-update/ |
| 138 | +- Slack `chat:write` scope: https://docs.slack.dev/reference/scopes/chat.write/ |
| 139 | +- Slack AI app guidance: https://docs.slack.dev/ai/developing-ai-apps |
| 140 | +- Chat SDK Slack adapter: https://chat-sdk.dev/adapters/slack |
0 commit comments