Prove that Slack holds this message in a direct message conversation. The post event states the channel_type im, so the message reached a direct message conversation and not a public channel. It does not prove which person.

Contract identity.
FactValue
Contract idslack.direct_message.posted
Version1.0.0
Hash8619feda2b62da0a
Completion levelposted_to_user
PublisherBuilt and signed by Provely.
CertificationProvisional
SkillSlack Web API 0.1.0
Valid for provider API versionsfp_2026_09

What is the intent?

Send the message to the person as a direct message.

What is the subject and the action?

MemberValue
Subject typeslack.message
Subject identitymessage_ts = $action.result.ts
Canonical effectmessaging.message_post
Provider operationPOST /chat.postMessage
Idempotencynone, retry is not safe

How does the evidence correlate with this operation?

StrategyAssuranceKeysRequired
resource_idstrongmessage_ts from $action.result.tsyes
fingerprintweakchannel from $input.channel_id; text from $input.textno

Which evidence does the contract require?

Minimum evidence level E2. An independent channel is required. Minimum channels: 1.

ChannelLevelIndependenceVerifierDescription
message_readbackE2provider readbackhttpRead the one message of the conversation that carries this ts. The documented recipe sets oldest to the ts, inclusive to true, and limit to 1. A condition path is $observed.message_readback.messages[0].ts. The path $observed.message_readback.ok states whether Slack answered.
direct_message_posted_eventE3provider eventwebhookThe message.im events of this message in the intended direct message conversation. The webhook verifier returns {events, count, latest, earliest, types, duplicates_dropped}. The value im of channel_type separates a direct message from every other conversation.
message_conversation_postsE3provider eventwebhookThe messages of this text in this conversation since the operation started. The webhook verifier returns {events, count, latest, earliest, types, duplicates_dropped}. A count above one shows a second post, and chat.postMessage has no idempotency key to stop it.

Which conditions must all hold for VERIFIED?

ConditionMeaningPathOperatorExpectedEvidence
read_succeededSlack answered the read. Every Web API response carries the boolean member ok, and Slack answers HTTP 200 for a failure as well, so the status code states nothing.$observed.message_readback.okeqtruemessage_readback
message_presentThe conversation holds exactly one message at this ts. A hidden message, such as a deleted one, leaves the list.$observed.message_readback.messagesarray_length1message_readback
message_ts_matchesThe ts of the message equals the ts of the answer of chat.postMessage. The member is a string in both places.$observed.message_readback.messages[0].tseq$action.result.tsmessage_readback
message_text_matchesThe text of the message equals the text that the intent stated.$observed.message_readback.messages[0].texteq$input.textmessage_readback
message_posted_by_an_appThe message carries the subtype bot_message, so an integration posted it. A message of a person states no subtype.$observed.message_readback.messages[0].subtypeeqbot_messagemessage_readback
message_posted_in_the_windowSlack posted the message after the operation started. The ts of a message is a Unix timestamp, and the bounds oldest and latest read the same values.$observed.message_readback.messages[0].tstime_after$operation.created_atmessage_readback
direct_message_event_names_an_im_conversationAt least one message.im event of this message names the conversation of the intent and states the channel_type im. A workspace with no event subscription cannot verify this level.$observed.direct_message_posted_event.countgte1direct_message_posted_event

Which conditions give CONTRADICTED?

ConditionClassReasonPathOperatorExpected
message_text_differswrong subjectSlack holds a different text than the intent stated. Ask a person.$observed.message_readback.messages[0].textne$input.text
message_predates_operationpre existing stateThe message is older than the operation. It proves nothing.$observed.message_readback.messages[0].tstime_before$operation.created_at
duplicate_message_presentduplicate side effectSlack holds more than one message of this text in this conversation since the operation started. Do not retry.$observed.message_conversation_posts.countgt1

Which observed states map to a verdict before completion?

RuleMatchVerdictReason
read_refused$observed.message_readback.ok eq falseUNVERIFIABLESlack answered the read with the status code 200 and the member ok false. The answer is a refusal and it is no evidence.

How long does the runtime observe?

Timing memberValue
Initial delay1000 ms
Poll interval5000 ms
Backoffexponential factor 2, max 60000 ms
Maximum attempts40
Timeout900000 ms
Stale read window20000 ms
On timeoutUNVERIFIABLE (evidence_unavailable_before_timeout), escalated to a person

Where do these rules come from?

  • slack.openapi#/paths/~1chat.postMessage/post: slack.openapi, retrieved 2026-09-08
  • slack.docs.post_message#post-a-message/post-to-a-direct-message-conversation: slack.docs.post_message, retrieved 2026-09-08
  • slack.docs.conversations#conversations/open-a-direct-message-conversation: slack.docs.conversations, retrieved 2026-09-08
  • slack.docs.conversations#conversations/read-one-conversation: slack.docs.conversations, retrieved 2026-09-08
  • slack.openapi#/components/schemas/ConversationsHistoryResponse/properties/ok: slack.openapi, retrieved 2026-09-08
  • slack.docs.web_api#web-api/the-ok-member: slack.docs.web_api, retrieved 2026-09-08
  • slack.docs.web_api#web-api/a-failure-carries-the-status-code-200: slack.docs.web_api, retrieved 2026-09-08
  • slack.openapi#/components/schemas/ConversationsHistoryResponse/properties/messages: slack.openapi, retrieved 2026-09-08
  • slack.docs.conversations#conversations/read-one-message: slack.docs.conversations, retrieved 2026-09-08
  • slack.docs.conversations#conversations/a-hidden-message: slack.docs.conversations, retrieved 2026-09-08
  • slack.openapi#/components/schemas/Message/properties/ts: slack.openapi, retrieved 2026-09-08
  • slack.openapi#/components/schemas/ChatPostMessageResponse/properties/ts: slack.openapi, retrieved 2026-09-08
  • slack.openapi#/components/schemas/Message/properties/text: slack.openapi, retrieved 2026-09-08
  • slack.docs.post_message#post-a-message/the-response: slack.docs.post_message, retrieved 2026-09-08
  • slack.openapi#/components/schemas/Message/properties/subtype: slack.openapi, retrieved 2026-09-08
  • slack.docs.post_message#post-a-message/the-subtype-of-a-message-that-an-app-posts: slack.docs.post_message, retrieved 2026-09-08
  • slack.docs.conversations#conversations/read-the-history-of-a-conversation: slack.docs.conversations, retrieved 2026-09-08
  • slack.events#/events/message.im: slack.events, retrieved 2026-09-08
  • slack.docs.events#events-api/the-message-subscriptions: slack.docs.events, retrieved 2026-09-08
  • slack.openapi#/components/schemas/Conversation/properties/is_im: slack.openapi, retrieved 2026-09-08

Can slack.direct_message.posted return VERIFIED from the action response alone?

No. The minimum evidence level is E2. The action response is E1. The completion conditions read message_readback and direct_message_posted_event.

What happens after the timeout?

The verdict is UNVERIFIABLE with the reason evidence_unavailable_before_timeout. The operation goes to a person for review.