Skip to main content

Slack Post ExecModule

Overview

SlackPostModule creates one message through Slack Web API chat.postMessage. It supports bounded text, up to fifty Block Kit objects, and an optional thread timestamp.

Version 2.0 replaces the catalog's empty input/output metadata and unsafe delivery model. The module now requires a READY bot-token IntegrationAccount, accepts conversation identifiers instead of ambiguous channel names, bounds payload size, disables link and media unfurling, blocks broadcast mentions by default, validates the provider timestamp and channel, and sanitizes provider failures.

Message creation is an external, non-idempotent side effect. The module never retries HTTP 429, 5xx, timeout, or ambiguous network failures automatically, because Slack may have committed the message before the client observed the failure.

Usage

  1. Create or select a Slack app with a bot user.
  2. Grant the bot chat:write and invite it to each target conversation as required by Slack.
  3. Store the xoxb-... bot token in the encrypted apiKey field of a ValkyrAI IntegrationAccount, set the account to READY, and bind it through ExecModuleConfig.authConfig.integrationAccount.
  4. Add SlackPostModule to a workflow and provide channel_id.
  5. Supply non-empty text, at least one Block Kit object, or both.
  6. Add thread_ts for a reply. Set allow_broadcast_mentions only when an approved workflow intentionally uses <!channel>, <!here>, or <!everyone>.
  7. Require outbound approval where policy demands it and retain the returned timestamp as reconciliation evidence.

Inputs

NameTypeRequiredDescriptionConstraints
channel_idstringYesSlack public channel, private channel, or direct-message identifier.Starts with C, G, or D, followed by 8–31 uppercase letters or digits. Channel names such as #general are rejected. Legacy channel is accepted as an alias.
textstringConditionalMessage text and accessibility fallback for Block Kit clients.At most 40,000 Unicode code points; required when blocks is absent or empty.
blocksarray of objectsConditionalSlack Block Kit layout objects.At most 50 objects; Slack applies final per-block and aggregate validation.
thread_tsstringNoParent message timestamp for a threaded reply.10–16 digit seconds component, a period, then exactly six fractional digits.
allow_broadcast_mentionsbooleanNoPermit Slack broadcast mention tokens in text or blocks.Defaults to false; must be explicitly true for <!channel>, <!here>, or <!everyone>.

The complete serialized request is limited to 100,000 UTF-8 bytes. mock is rejected and cannot fabricate delivery.

Outputs

NameTypeWhen presentDescription
slack.message.tsstringSuccessMessage timestamp returned by Slack and validated against the Slack timestamp format.
slack.message.channelstringSuccessProvider channel identifier, verified against channel_id.
slack.message.statusstringAlwaysSENT after a validated success response or ERROR on failure.

The runtime ExecModule is also marked GOOD or ERROR. EventLogs contain bounded progress and sanitized failure details; tokens and provider bodies are not written to WorkflowState or errors.

IntegrationAccount Requirements

SettingRequirement
ProviderSlack Web API
AuthenticationBot token
StatusREADY
accountNameHuman-readable Slack app or bot identity
apiKeyEncrypted xoxb-... bot token
RelationshipBind through ExecModuleConfig.authConfig.integrationAccount

The bot needs chat:write and access to the selected conversation. Depending on the workspace and operation, Slack may also require membership or additional scopes. Never place the token in payload fields, text, blocks, URLs, logs, or documentation examples.

Configuration

Illustrative normalized configuration:

{
"version": "2.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:slack-release-bot"
},
"payloadConfig": {
"parameters": "{\"channel_id\":\"C0123456789\",\"text\":\"Release verified.\",\"thread_ts\":\"1723046400.123456\"}"
}
}

The account value is a symbolic secure reference. Persisted workflows use the generated IntegrationAccount relationship, never a plaintext token.

The default transport has a 10-second connection timeout and a 30-second read timeout. The payload always sets link_names, unfurl_links, and unfurl_media to false. Broadcast mention tokens require the explicit safety override even though automatic channel-name linking is disabled.

Operations

SlackPostModule performs one chat.postMessage operation with compatible shapes:

ShapeProvider payloadSide effect
Text messagechannel, textCreates one channel message.
Block Kit messageblocks with optional text fallbackCreates one message with up to fifty layout blocks.
Threaded replyText or blocks plus thread_tsCreates one reply under the referenced parent message.
Approved broadcastText or blocks containing a broadcast token plus allow_broadcast_mentions=trueCreates one message that can notify a broad audience.

File upload, remote-file sharing, scheduled messages, ephemeral messages, updates, deletion, reactions, canvases, workflows, bot impersonation, and bulk sends are separate operations and are not implemented here.

Errors and Failure Modes

FailureCauseRetry guidance
Validation failureMissing content, channel name instead of ID, malformed thread timestamp, too many blocks, non-object block, unsafe broadcast mention, or payload overflow.Correct the configuration; no Slack request was sent.
IntegrationAccount failureNo bound account, non-READY status, blank token, or token that is not an xoxb bot token.Bind or repair the Slack bot account; no Slack request was sent.
Slack ok: falseProvider rejects the request with a bounded error code such as channel_not_found.Correct account scopes, membership, channel, or payload before a new attempt.
HTTP 401/403Invalid token, missing scopes, or access denied.Rotate or reauthorize the IntegrationAccount and bot access.
HTTP 429Slack rate limit.Reconcile whether the message exists, honor provider rate-limit guidance, then schedule a deliberate new attempt.
HTTP 5xx or network failureProvider or transport failure with an ambiguous commit boundary.Do not retry blindly; inspect the target conversation first.
Invalid success responseA 2xx body is not JSON, lacks ok: true, has no valid ts, or returns a different channel.Treat as failure and inspect provider compatibility; success is not recorded.

Provider response bodies can contain workspace data or credential-like details. HTTP failures therefore expose only a sanitized status, while ok: false exposes only a strictly bounded lowercase provider error code.

Example

Create a threaded release notification with an accessibility fallback:

{
"channel_id": "C0123456789",
"text": "Release verified.",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Release verified*\nProduction route checks passed."
}
}
],
"thread_ts": "1723046400.123456"
}

Expected result shape after Slack returns a verified message:

{
"slack.message.ts": "1723046500.654321",
"slack.message.channel": "C0123456789",
"slack.message.status": "SENT"
}

Notes

  • Pagination: not applicable; one execution attempts one message creation.
  • Limits: local validation enforces 40,000 text code points, 50 blocks, a 100,000-byte request body, channel and timestamp formats, and an explicit broadcast-mention opt-in. Slack applies final Block Kit, text, workspace, scope, and account limits.
  • Accessibility: include text when using blocks so notifications and assistive clients have a fallback.
  • Unfurling: links and media are not unfurled by default, which reduces unexpected remote fetches and visual expansion.
  • Mentions: channel-name linking is disabled. Broadcast tokens are blocked unless allow_broadcast_mentions=true; direct user or user-group mention syntax remains Slack-controlled and should be reviewed as outbound content.
  • Rate limits: HTTP 429 is surfaced without retry. The module does not persist rate-limit headers.
  • Idempotency: message creation is non-idempotent. A workflow retry can create a duplicate, and WorkflowState is not treated as durable provider deduplication across ambiguous failures.
  • API constraints: channel names are not accepted because name resolution can drift; use the stable conversation ID from Slack.
  • Destructive behavior: creation is an external outbound write. This module cannot delete or compensate a message; removal requires a separately authorized operation.
  • Observability: EventLogs record validation, submission, success timestamp, or sanitized failure. Message text, blocks, bot tokens, and provider bodies are excluded from failure logs.
  • Unverified boundary: deterministic tests cover IntegrationAccount binding, exact request construction, limits, broadcast safety, response mapping, non-retry behavior, metadata serialization, and secret redaction. Live Slack execution requires separately authorized service credentials and is not exercised in repository tests.

See Slack's official chat.postMessage method, Block Kit reference, and rate-limit documentation for current provider behavior.