Skip to main content

Microsoft Teams Post ExecModule

Overview

TeamsPostModule creates one text or HTML chatMessage in a Microsoft Teams channel through Microsoft Graph. Version 2.0 requires a READY IntegrationAccount containing a delegated work-or-school access token, validates stable team and channel identifiers, bounds content and serialized payload size, blocks active HTML, verifies the returned message identity and Teams URL, and exposes only secret-safe failures.

Microsoft Graph permits normal channel message creation with delegated ChannelMessage.Send. Its application permission is Teamwork.Migrate.All, which Microsoft limits to migration. This module therefore does not exchange a client ID and client secret or support application-only posting.

Usage

  1. Register a Microsoft Entra application that supports delegated work-or-school authorization.
  2. Grant the least-privileged ChannelMessage.Send delegated permission and complete the required consent flow.
  3. Obtain an access token for the signed-in user and store it only in a ValkyrAI IntegrationAccount apiKey.
  4. Mark the account READY, bind it through ExecModuleConfig.authConfig.integrationAccount, and select the stable team and channel identifiers.
  5. Supply content and choose text or html.
  6. Route the outbound message through any required human-approval policy, then execute once.

Use this module only for messages people are expected to read. Microsoft explicitly prohibits treating Teams as a log sink.

Inputs

NameTypeRequiredDescriptionLocal constraints
team_idstringYesStable Microsoft Teams team identifier.UUID-shaped value; display names are rejected. Legacy teamId is accepted.
channel_idstringYesStable Teams channel identifier.1–256 characters from the bounded Graph identifier character set. Legacy channelId is accepted.
contentstringYesText or HTML message body.1–20,000 Unicode code points. Legacy text and html are accepted.
content_typestringNoGraph body type.text or html; defaults to text. Legacy contentType is accepted.

The complete serialized request is limited to 28,000 UTF-8 bytes. mock is rejected and cannot fabricate delivery. HTML rejects active elements, event-handler attributes, and javascript: or data: URLs; Microsoft Graph applies final markup validation.

Outputs

NameTypeWhen presentDescription
teams.message.idstringSuccessMicrosoft Graph message identifier returned by the create operation.
teams.message.web_urlstringSuccessHTTPS teams.microsoft.com URL returned for the created message.
teams.message.statusstringAlwaysSENT after a validated 201 response or ERROR on failure.

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

IntegrationAccount Requirements

SettingRequirement
ProviderMicrosoft Graph / Microsoft Teams
AuthenticationDelegated work-or-school OAuth access token
StatusREADY
accountNameHuman-readable tenant and user identity
apiKeyEncrypted delegated access token
passwordUnused; client-secret exchange is intentionally unsupported
RelationshipBind through ExecModuleConfig.authConfig.integrationAccount

The token needs delegated ChannelMessage.Send, the user must be authorized for the target team and channel, and tenant policy can impose additional consent or conditional-access requirements. Never put the token in content, URLs, payload parameters, logs, documentation examples, or error text.

Configuration

Illustrative normalized configuration:

{
"version": "2.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:teams-release-user"
},
"payloadConfig": {
"parameters": "{\"team_id\":\"12345678-1234-1234-1234-1234567890ab\",\"channel_id\":\"19:release-updates@thread.tacv2\",\"content\":\"Release verified.\",\"content_type\":\"text\"}"
}
}

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.

Operations

TeamsPostModule performs exactly one operation:

POST /v1.0/teams/{team-id}/channels/{channel-id}/messages
ShapeProvider payloadSide effect
Textbody.contentType=text and bounded contentCreates one channel message.
HTMLbody.contentType=html and bounded, locally screened markupCreates one formatted channel message.
Legacy texttext without contentNormalizes to a text message.
Legacy HTMLhtml without contentNormalizes to an HTML message.

Replies, chats, mentions, hosted content, attachments, reactions, updates, deletes, imports, bulk sends, webhook cards, and application-only migration are separate operations and are not implemented here.

Errors and Failure Modes

FailureCauseRetry guidance
Validation failureMissing or malformed IDs, missing content, unsupported content type, active HTML, content overflow, or payload overflow.Correct the configuration; no Graph request was sent.
IntegrationAccount failureNo bound account, non-READY status, or blank delegated token.Bind or reauthorize the delegated account; no Graph request was sent.
HTTP 401/403Expired token, missing delegated scope, channel access denial, consent policy, or application-only token.Reauthorize the account with delegated ChannelMessage.Send and verify target access.
HTTP 429Microsoft Graph throttling.Reconcile whether the message exists, honor provider 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 channel first.
Invalid success responseThe response is not 201 JSON, lacks a valid ID or Teams URL, or identifies a different team/channel.Treat as failure and inspect provider compatibility; success is not recorded.

Provider bodies can contain tenant data or credential-like details. HTTP failures expose only the sanitized status. Errors are rethrown without retaining the provider exception as a cause.

Example

Create a plain-text release notification:

{
"team_id": "12345678-1234-1234-1234-1234567890ab",
"channel_id": "19:release-updates@thread.tacv2",
"content": "Release verified. Production route checks passed.",
"content_type": "text"
}

Expected result shape after Microsoft Graph returns a verified message:

{
"teams.message.id": "1723046500654",
"teams.message.web_url": "https://teams.microsoft.com/l/message/19:release-updates@thread.tacv2/1723046500654",
"teams.message.status": "SENT"
}

Notes

  • Pagination: not applicable; one execution attempts one message creation.
  • Limits: local validation enforces 20,000 content code points and a 28,000-byte JSON body. Microsoft Graph and Teams enforce final service, tenant, and markup limits.
  • Idempotency: channel message creation is non-idempotent. A workflow retry can create a duplicate, and WorkflowState is not treated as provider deduplication across ambiguous failures.
  • Rate limits: HTTP 429 is surfaced without retry. The module does not retain rate-limit headers or provider response bodies.
  • API constraints: the normal create-message flow requires delegated work-or-school authorization. Application permission is reserved for migration and is outside this module.
  • HTML: only passive bounded markup is accepted locally. Active elements, inline event handlers, and executable URL schemes fail before transport.
  • 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, message ID, or sanitized failure. Message content, tokens, and provider bodies are excluded from failure logs.
  • Unverified boundary: deterministic tests cover IntegrationAccount binding, exact request construction, legacy aliases, bounds, HTML safety, response mapping, non-retry behavior, metadata serialization, and secret redaction. Live Microsoft Graph execution requires separately authorized delegated credentials and is not exercised in repository tests.

See Microsoft's official channel message create API, Microsoft Graph permissions reference, and authorization code flow for current provider behavior.