Skip to main content

Discord Post ExecModule

Overview

DiscordPostModule creates one message through POST /channels/{channel.id}/messages on Discord API v10. It supports message content, up to ten embed objects, bounded HTTPS links, and an optional reply reference.

Version 2.0 replaces the catalog's empty input/output metadata and unsafe retry model. The module no longer claims that URL values are uploaded as Discord attachments: link_urls are appended to message content, while actual binary file upload remains outside this module. A legacy attachments array is accepted as the same bounded link list for workflow compatibility.

Message creation is an outbound, non-idempotent action. The module validates the full request before transport, disables automatic mentions by default, requires a valid Discord message identifier in the success response, and never retries HTTP 429, 5xx, timeout, or ambiguous network failures automatically.

Usage

  1. Create a Discord application and bot, then add the bot to the target server.
  2. Grant the bot View Channel and Send Messages; grant Embed Links when using embeds.
  3. Store the 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 DiscordPostModule to a workflow and set channel_id.
  5. Provide non-empty content, at least one embed, or at least one HTTPS link.
  6. Require outbound approval where policy demands it, then inspect the returned message ID before continuing.

Inputs

NameTypeRequiredDescriptionConstraints
channel_idstringYesDiscord channel snowflake.17–20 decimal digits.
contentstringConditionalMessage text.Content plus appended links must be at most 2,000 Unicode code points.
embedsarray of objectsConditionalDiscord embed objects passed to API v10.At most ten objects; Discord performs final field and aggregate embed validation.
link_urlsarray of stringsConditionalHTTPS links appended to content on separate lines.At most ten; no URL credentials or fragments; each URL is at most 2,048 characters.
reply_to_message_idstringNoExisting message in the target channel to reply to.17–20 decimal digits. Missing referenced messages do not make Discord reject the create request.

At least one of content, embeds, or link_urls is required. Legacy attachments is accepted as an alias for link_urls; it does not perform multipart file upload.

Outputs

NameTypeWhen presentDescription
discord.message.idstringSuccessMessage snowflake returned by Discord.
discord.message.channel_idstringSuccessProvider channel identifier, verified against the requested channel.
discord.message.statusstringAlwaysSENT after a validated success response or ERROR on failure.

The module also marks the runtime ExecModule GOOD or ERROR and emits bounded EventLog progress. Bot tokens and provider response bodies are never written to WorkflowState or failure events.

IntegrationAccount Requirements

SettingRequirement
ProviderDiscord REST API v10
AuthenticationBot token
StatusREADY
accountNameHuman-readable Discord bot identity
apiKeyEncrypted bot token used as Authorization: Bot ...
RelationshipBind through ExecModuleConfig.authConfig.integrationAccount

The bot must be a member of the server and authorized for the selected channel. Never place the token in payload fields, message content, logs, URL query parameters, or documentation examples.

Configuration

Illustrative normalized configuration:

{
"version": "2.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:discord-release-bot"
},
"payloadConfig": {
"parameters": "{\"channel_id\":\"123456789012345678\",\"content\":\"Release complete.\",\"link_urls\":[\"https://status.example.com/releases/42\"],\"reply_to_message_id\":\"345678901234567890\"}"
}
}

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

The default transport has a 10-second connection timeout and a 30-second read timeout. Message creation is not retried automatically because a timeout or upstream error may occur after Discord committed the message.

Operations

DiscordPostModule performs one create-message operation with compatible shapes:

ShapeProvider payloadSide effect
Text messagecontentCreates one channel message.
Embed messageembeds with optional contentCreates one message containing up to ten embeds.
Link messagelink_urls appended to contentCreates one message containing HTTPS links; no files are uploaded.
ReplyAny shape plus message_referenceCreates one message referencing another message in the target channel.

Multipart attachments, editing, deletion, reactions, threads, components, polls, scheduled sends, bulk sends, and webhook impersonation are separate operations and are not implemented here.

Errors and Failure Modes

FailureCauseRetry guidance
Validation failureMissing content, malformed snowflake, non-array embeds or links, too many items, unsafe URL, or length overflow.Correct the configuration; no Discord request was sent.
IntegrationAccount failureNo bound account, non-READY account, or blank apiKey.Bind or repair the Discord bot account; no Discord request was sent.
HTTP 400/404Invalid payload, channel, reply reference, or provider constraint.Correct the request before a new attempt.
HTTP 401/403Invalid token, missing bot membership, or insufficient channel permissions.Rotate or reauthorize the IntegrationAccount and bot permissions.
HTTP 429Discord 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; check the channel first.
Invalid success responseA 2xx response lacks a snowflake id, has a different channel_id, or is not valid JSON.Treat as failure and inspect provider compatibility; success is not recorded.

Provider response bodies can contain user content or credential-like details, so failures expose only a sanitized HTTP status or bounded local validation message.

Example

Create a deployment notification with one embed and one release link:

{
"channel_id": "123456789012345678",
"content": "Release complete.",
"embeds": [
{
"title": "Release 42",
"description": "Production verification passed.",
"color": 5793266
}
],
"link_urls": ["https://status.example.com/releases/42"]
}

Expected result shape after Discord returns a valid message object:

{
"discord.message.id": "234567890123456789",
"discord.message.channel_id": "123456789012345678",
"discord.message.status": "SENT"
}

Notes

  • Pagination: not applicable; one execution attempts one message creation.
  • Limits: local validation enforces the 2,000-code-point content limit, ten embeds, ten links, and bounded link lengths. Discord applies final embed, payload, permission, and account limits.
  • Mentions: allowed_mentions.parse is empty, so content does not automatically expand @everyone, role, or user mentions.
  • Rate limits: HTTP 429 is surfaced without retry. Discord may return provider-specific rate-limit headers, but the module does not expose or persist them.
  • Idempotency: message creation is non-idempotent. A workflow retry can create a duplicate message, and this module does not claim durable deduplication across ambiguous failures.
  • API constraints: reply references are scoped to the configured channel and use fail_if_not_exists: false; Discord can create the message without a reply link when the referenced message is absent.
  • 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 ID, or sanitized failure. Message content, bot tokens, and provider bodies are excluded from failure logs.
  • Unverified boundary: deterministic tests cover account binding, exact request construction, validation, response mapping, mention suppression, non-retry behavior, metadata serialization, and secret redaction. Live Discord execution requires separately authorized service credentials and is not exercised in repository tests.

See Discord's official Create Message resource and permissions reference for current provider behavior.