MINARA
Minara 사용하기클라이언트 및 인터페이스메시징 플랫폼

Slack

Bot 토큰 모드는 전체 Slack Web API(스트리밍, 파일, 반응, 임시 메시지, 예약 전송)를 활성화합니다. Webhook 모드는 단일 URL 폴백으로, 일반 텍스트, Block Kit 블록, 스레드 답글을 지원합니다.

🟢 런타임 즉시 사용 가능. 설정된 환경 변수에 따라 두 가지 모드 중 하나가 자동으로 선택됩니다. 사소하지 않은 모든 용도에는 Bot 토큰 모드를 권장합니다. Webhook 모드는 단일 URL 폴백으로, 텍스트 / Block Kit 블록 / 스레드 답글은 지원하지만 스트리밍, 첨부 파일, 반응, 임시 전달, 예약 전달, metadata 필드는 지원하지 않습니다.

모드 선택

모드환경 변수스트리밍첨부 파일스레드반응블록 (Block Kit)임시 / 예약 / Metadata인바운드적합한 경우
Bot 토큰 (권장)SLACK_BOT_TOKEN + SLACK_CHANNEL_ID전체 기능 통합, 다중 채널 라우팅, 인바운드 리스너
Webhook (Slack 앱 없는 폴백)SLACK_WEBHOOK_URL일반 텍스트, Block Kit, 스레드 답글 (Slack 앱 승인 불필요)

Webhook 모드의 지원 범위: Slack의 Incoming Webhooks 문서에 따르면, Webhook URL은 JSON 본문에서 text, blocks, thread_ts, mrkdwn, unfurl_links, unfurl_media를 허용합니다. 단, 편집 엔드포인트(스트리밍 불가), files.upload(첨부 파일 불가), reactions.add, chat.postEphemeral, chat.scheduleMessage, metadata는 지원하지 않습니다. 이는 Minara의 제한이 아니라 Bot 토큰 전용 Slack Web API 메서드입니다. 어떤 Slack SDK도 이를 우회할 수 없습니다.

두 환경 변수 세트가 모두 존재할 때의 우선순위: Minara는 Bot 모드(SLACK_BOT_TOKEN + SLACK_CHANNEL_ID)를 먼저 선택합니다. Bot 자격 증명이 없거나 불완전할 때만 Webhook이 사용됩니다. Bot 환경 변수 중 하나를 제거하면 Webhook 모드로 전환됩니다.

설정, Bot 토큰 모드 (권장)

1. Bot 생성

  1. api.slack.com/apps를 열고, Create New AppFrom scratch → 이름을 "Minara"로 지정 → 워크스페이스 선택
  2. OAuth & Permissions 아래에서 다음 Bot Token Scopes를 추가합니다.
    • chat:write: chat.postMessage / chat.postEphemeral / chat.scheduleMessage에 필요
    • chat:write.public: Bot이 초대되지 않은 채널에 게시하는 데 필요
    • files:write: files.v2를 통한 첨부 파일 업로드에 필요
    • reactions:write: add_reaction 도구에 필요
  3. 상단의 Install to Workspace를 클릭하고 Bot User OAuth Token(xoxb-로 시작)을 복사합니다.

2. 채널 ID 확인

Slack 클라이언트에서 채널 이름을 클릭하고 하단으로 스크롤하여 채널 ID(예: C0123ABC)를 복사합니다.

3. Minara 설정

프로젝트 루트의 .env 파일에서 SLACK_WEBHOOK_URL설정 해제되어 있는지 확인합니다. 함께 설정되어 있어도 Bot 모드가 우선되지만, 활성 모드를 명확히 하려면 제거하는 것이 깔끔합니다. 그런 다음 아래를 입력합니다.

SLACK_BOT_TOKEN=xoxb-...
SLACK_CHANNEL_ID=C0123ABC

4. 테스트

minara auth messaging test slack

설정, Webhook 모드 (폴백)

Bot 토큰 모드를 우선적으로 사용하십시오. Webhook은 개인 워크스페이스나 제한된 엔터프라이즈 플랜에서 Slack 앱 승인을 받을 수 없거나, 단순 텍스트 알림 채널을 최소한의 설정으로 구성해야 할 때만 사용하십시오.

1. Incoming Webhook 생성

  1. api.slack.com/appsCreate New AppFrom scratch → 이름을 "Minara"로 지정 → 워크스페이스 선택
  2. 왼쪽 내비게이션 → Incoming Webhooks → 기능 On으로 전환
  3. Add New Webhook to Workspace → 채널 선택 → Allow
  4. Webhook URL(https://hooks.slack.com/services/T00/B00/xxx)을 복사합니다.

2. Minara 설정

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00/B00/xxx

채널은 URL에 포함되어 있으므로 SLACK_CHANNEL_ID는 무시되며, send_messagechannel 재정의는 명확한 오류와 함께 거부됩니다. Webhook 모드는 스레드, Block Kit 블록, mrkdwn, unfurl 토글을 지원합니다. 단, 첨부 파일, 임시 전달, 예약 전달, metadata는 지원하지 않습니다.

스트리밍 동작 (Bot 모드 전용)

Slack의 chat.update는 Tier-3 속도 제한(분당 약 50회)을 적용합니다. Minara는 편집 주기를 1,200ms로 제한하여 상한선을 여유 있게 유지하면서도 충분히 빠른 응답성을 제공합니다. 메시지 최대 길이는 40,000자이며 실제로는 거의 도달하지 않습니다.

리치 메시징, Block Kit, 임시 메시지, 예약 전송, Metadata (Bot 모드)

Bot 모드 Slack의 send_messageprovider_options.slack 객체를 허용하며, 이는 해당 Slack Web API 필드 및 엔드포인트로 직접 라우팅됩니다. 핵심 필드인 text / channel / thread는 동일한 호출에서 provider_options.slack과 함께 사용할 수 있습니다.

attachments는 예외입니다. 첨부 파일은 Slack의 Files v2 플로우(files.getUploadURLExternalfiles.completeUploadExternal)를 통해 라우팅되며, initial_comment(text에서 채워짐)와 thread_ts만 허용합니다. attachments와 함께 blocks / mrkdwn / unfurl_* / metadata / ephemeral_user / schedule_at을 전달하면 도구 경계에서 거부됩니다. 우회 방법: 먼저 리치 메시지를 게시하여 messageId를 얻은 후, 해당 스레드에 파일을 별도로 업로드하십시오.

Block Kit 리치 포맷팅

Slack의 Block Kit은 표준 리치 메시지 형식으로, 헤더, 섹션, 구분선, 컨텍스트, 필드, 이미지를 지원합니다. blockschat.postMessageblocks 파라미터로 직접 전달되는 블록 객체 배열입니다. text는 모바일 알림, 스크린 리더, 접근성 도구를 위한 일반 텍스트 폴백으로 유지됩니다.

send_message({
  provider: "slack",
  text: "BTC -5.1% on 1h",  // 폴백: blocks를 렌더링할 수 없을 때 표시
  provider_options: {
    slack: {
      blocks: [
        { type: "header", text: { type: "plain_text", text: "Price alert" } },
        { type: "section", text: { type: "mrkdwn", text: "*BTC* dropped *5.1%* in the last hour" } },
        { type: "divider" },
        {
          type: "context",
          elements: [
            { type: "mrkdwn", text: "_Source: Minara · 1h · $68,450_" },
          ],
        },
      ],
    },
  },
})

Slack의 Block Kit Builder에서 블록 레이아웃을 반복 작업한 후, 결과 JSON을 blocks에 바로 붙여넣으십시오.

임시 메시지, 특정 사용자에게만 표시

ephemeral_user에 Slack 사용자 ID(예: U012ABC)를 설정하면 전송이 chat.postEphemeral로 라우팅됩니다. 메시지는 해당 사용자에게만 표시되며 Slack을 새로고침하면 사라집니다. 채널 내 슬래시 커맨드 응답이나 사용자별 확인 메시지에 유용합니다.

send_message({
  provider: "slack",
  text: "Your position is under 1% of portfolio. Auto-trade skipped.",
  provider_options: { slack: { ephemeral_user: "U012ABC" } },
})

chat.postEphemeral의 인수 지원은 chat.postMessage의 엄격한 부분 집합입니다. Slack의 문서에 따르면, ephemeral 엔드포인트는 mrkdwn, unfurl_links, unfurl_media, metadata를 허용하지 않으며 text / blocks / thread_ts / attachments / 표준 인증 인수만 허용합니다. 누락된 필드를 ephemeral_user와 함께 전달하면 도구 경계에서 구체적인 오류와 함께 거부됩니다. 자동으로 무시되지 않습니다. Ephemeral 전송은 Minara의 attachments(Slack의 files.v2 플로우에 ephemeral 훅이 없음) 및 schedule_at(ephemeral 메시지 예약 불가)과도 호환되지 않습니다.

예약 메시지

schedule_at에 Unix 초 단위 타임스탬프를 설정하면 전송이 chat.scheduleMessage로 라우팅됩니다. Slack은 예약을 최대 120일 후로 제한하며, Minara도 동일한 제한을 도구 경계에서 적용합니다.

send_message({
  provider: "slack",
  text: "Weekly review — check the dashboard before stand-up",
  provider_options: {
    slack: { schedule_at: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60 },
  },
})

반환된 message_id는 Slack의 scheduled_message_id입니다. 취소가 필요하면 향후 도구를 통해 chat.deleteScheduledMessage에 전달하십시오. ephemeral_user와는 함께 사용할 수 없습니다.

metadata는 예약 메시지에서 지원되지 않습니다. Slack의 chat.scheduleMessage 문서에 따르면, metadata 파라미터가 포함된 예약 메시지는 "게시되지 않습니다." Minara는 이 조합을 도구 경계에서 거부하므로, 자동으로 전달되지 않는 전송에 대해 scheduled_message_id를 받는 상황을 방지합니다.

메시지별로 Slack의 기본 파싱 동작을 제어합니다.

  • mrkdwn: false: text의 마크다운 확장을 비활성화합니다(*not-bold*를 그대로 전송).
  • unfurl_links: false: 메시지 내 링크 미리보기를 억제합니다. 각 메시지에 큰 미리보기 카드가 생성되는 고빈도 알림에 유용합니다.
  • unfurl_media: false: 리치 미디어 미리보기를 억제합니다.

metadata, 기계가 읽을 수 있는 컨텍스트

메시지에 구조화된 JSON 페이로드를 첨부합니다(Slack 최대 8KB). UI에는 표시되지 않으며, 인바운드 핸들러가 렌더링된 텍스트가 아닌 LLM이 추론한 원시 데이터를 필요로 할 때 유용합니다.

send_message({
  provider: "slack",
  text: "BTC dropped 5%",
  provider_options: {
    slack: {
      metadata: {
        event_type: "price_alert",
        event_payload: { symbol: "BTC", pct: -5.1, ts: Date.now() },
      },
    },
  },
})

채널 재정의 (Bot 모드 전용)

send_message({
  provider: "slack",
  channel: "C9876XYZ",
  text: "Critical: position liquidation imminent",
})

Bot은 재정의 채널의 멤버이거나 chat:write.public 스코프를 보유해야 합니다.

문제 해결

"Webhook URL is disabled"

  • 앱이 워크스페이스에서 제거되었거나 앱 설정에서 Webhook이 수동으로 취소된 경우입니다.
  • Webhook을 재생성하고 SLACK_WEBHOOK_URL을 교체하십시오.

"channel_not_found" (Bot 모드)

  • Bot이 채널의 멤버가 아닙니다. 대상 채널에서 /invite @your-bot으로 초대하거나, chat:write.public 스코프를 추가하십시오.

"not_authed" / "invalid_auth"

  • SLACK_BOT_TOKEN이 없거나 잘못되었습니다. Bot 토큰은 xoxb-로 시작합니다. 사용자 토큰(xoxp-)은 작동하지 않으며, Slack API가 chat.postMessage에 대해 이를 거부합니다.

"Streaming not working"

  • Webhook 모드일 가능성이 높습니다. SLACK_BOT_TOKENSLACK_CHANNEL_ID가 모두 설정되어 있는지 확인하십시오.

"invalid_blocks" / "missing_scope" (Block Kit 사용 시)

  • Slack API는 자체 JSON 스키마에 따라 Block Kit을 검증합니다. Minara는 해당 스키마 검사를 복제하지 않습니다. Block Kit Builder에서 문제가 있는 블록을 찾아 수정하십시오.
  • missing_scope는 일반적으로 files:write(첨부 파일용) 또는 reactions:write(add_reaction용) 스코프가 누락된 경우입니다. 스코프 추가 후 앱을 재설치하십시오.

참조

목차