| name | respond-to-slack-thread |
| description | Post a reply to a Slack thread. Use when the user asks to reply to, respond to, or follow up on a Slack thread. Handles fetching thread context and posting a reply.
|
respond-to-slack-thread
Post a reply to an existing Slack thread. Requires $SLACK_BOT_TOKEN with channels:history, channels:read, and chat:write OAuth scopes.
Step 1: Clarify inputs
Before proceeding, ensure you have:
- Channel ID: The Slack channel ID (e.g.
C0123456789). If the user gave a channel name, resolve it in Step 2.
- Thread timestamp (
thread_ts): The ts of the parent message (e.g. 1234567890.123456).
- If the user provided a Slack message link (e.g.
https://yourworkspace.slack.com/archives/C0123456789/p1234567890123456), parse it:
- Channel ID = the segment after
/archives/ (e.g. C0123456789)
thread_ts = the p-prefixed value at the end, with a decimal inserted 6 characters from the right (e.g. p1234567890123456 → 1234567890.123456)
- Reply content: What to say. If not provided, fetch the thread context (Step 3) and draft a reply based on it.
If $SLACK_BOT_TOKEN is not set, ask the user for it before proceeding.
Step 2: Resolve channel ID (if needed)
If you only have the channel name:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=200" | \
jq -r '.channels[] | select(.name == "<channel_name>") | .id'
If the list is paginated, follow the response_metadata.next_cursor value.
Step 3: Fetch thread context
Read the existing thread to understand the conversation before composing a reply:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/conversations.replies?channel=<CHANNEL_ID>&ts=<THREAD_TS>" | \
jq '.messages[] | {user, ts, text, attachments}'
Review all messages to understand what has already been said before drafting your response.
Step 4: Resolve user info (if needed)
To @mention someone by email:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/users.lookupByEmail?email=<email>" | \
jq -r '.user.id'
Use the resulting ID as <@USER_ID> in the message text.
Step 5: Post the reply
curl -s -X POST \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
--data "{
\"channel\": \"<CHANNEL_ID>\",
\"thread_ts\": \"<THREAD_TS>\",
\"text\": \"<MESSAGE_TEXT>\"
}" \
"https://slack.com/api/chat.postMessage" | jq '{ok, ts, error}'
For multi-line messages, use $'...' ANSI-C quoting so \n is interpreted as real newlines:
MESSAGE=$'First line\n\nSecond line'
curl -s -X POST \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
--data "$(jq -n --arg channel "<CHANNEL_ID>" --arg thread_ts "<THREAD_TS>" --arg text "$MESSAGE" \
'{channel: $channel, thread_ts: $thread_ts, text: $text}')" \
"https://slack.com/api/chat.postMessage" | jq '{ok, ts, error}'
Slack mrkdwn formatting
Slack uses its own mrkdwn syntax — do NOT use standard Markdown:
| Intent | Slack mrkdwn |
|---|
| @mention user | <@USER_ID> |
| Hyperlink | <https://example.com|link text> |
| Bold | *bold* |
| Italic | _italic_ |
| Strikethrough | ~strikethrough~ |
| Code (inline) | `code` |
| Code block | ```code block``` |
Step 6: Confirm
After posting, share the reply's permalink with the user:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/chat.getPermalink?channel=<CHANNEL_ID>&message_ts=<REPLY_TS>" | \
jq -r '.permalink'
Notes
- If the API returns
ok: false, check the error field and handle it — common errors include not_in_channel (bot must be invited to the channel) and missing_scope (token lacks required permissions).
- To post as the bot's configured name/icon rather than a user, ensure the token is a bot token (starts with
xoxb-).
- If
thread_ts is omitted, the message posts as a new top-level message rather than a reply.