# Architecture

`@cuylabs/agent-channel-slack` is the native Slack transport for
`@cuylabs/agent-core`.

```text
Slack
  -> @slack/bolt
    -> @cuylabs/agent-channel-slack
      -> @cuylabs/agent-core
```

M365/Azure Bot Service Slack is not part of this package anymore. Its transport
will release separately.

## Direct Slack Flow

In this package:

- Slack sends events directly to your Bolt app
- request verification uses the Slack signing secret
- replies, progressive updates, and native `chatStream` streaming use the Slack
  Web API directly
- Slack-native payloads are parsed into `SlackActivityInfo`
- Bolt's `Assistant` middleware can drive the Assistant pane with `setStatus`,
  `setSuggestedPrompts`, `setTitle`, feedback blocks, and task updates
- Block Kit actions and modal submissions can resolve agent-core approval and
  human-input requests through `createSlackInteractiveController(...)`
- Bolt auth can run in three shapes:
  - single-workspace token
  - Bolt-managed OAuth install and callback flow
  - custom `authorize()` for externally managed installation lookup

## Package Layers

- `createSlackBoltApp(...)`
  - lower-level host builder
  - owns Bolt `App` + `ExpressReceiver` construction and auth mode selection
  - use this when you need explicit Bolt/OAuth control
- `mountSlackAgent(...)`
  - classic one-liner for DMs, `app_mention`, and optionally plain channel
    messages
  - calls `createSlackBoltApp(...)`, mounts the Slack adapter, registers
    `receiver.router`, and can start the HTTP server
- `createSlackAssistantBridge(...)`
  - Bolt `Assistant` lifecycle bridge over `AgentTurnSource`
  - handles `threadStarted`, `threadContextChanged`, `userMessage`,
    `setStatus`, suggested prompts, titles, `chatStream`, and feedback blocks
- `mountSlackAgentApp(...)` / `mountSlackAgentAppSocket(...)`
  - unified Slack surface: Assistant pane, DMs, `app_mention`, feedback, and
    optional Slack-native approval/human-input interactivity
  - HTTP and Socket Mode share the same installer so behavior stays aligned

Classic channel turns also consume modern Bolt event helpers when present:
`sayStream(...)` is preferred over manually constructing `client.chatStream(...)`,
and thread-level `setStatus(...)` is exposed through ambient Slack turn context.

Plain channel-message behavior is intentionally a two-step application choice:
`respondToChannelMessages` controls registration, while `resolveMessage(info)`
is the local policy gate for each normalized `SlackActivityInfo`. The package
preserves Slack metadata such as `userId`, `threadTs`, `messageTs`, and
`parentUserId` when Slack provides it, but it does not choose product policies
such as allowlisted channels, mentioned-thread continuation, or original-user
thread ownership.

That split follows Bolt's own architecture instead of hiding it behind a custom
Slack runtime. It keeps advanced Slack concerns in the official SDK layer while
the channel package stays focused on bridging Slack turns into `agent-core`.
