Define a message action
src/requestApproval.tsx
"request-approval") is unique within the app, 1 to 64 characters from A-Z, a-z, 0-9,
_, . and -. An app has at most 10 message actions.
Because the handler answers with ExpenseApproval.insert(…), the app must also include that block.
Leaving it out makes the app incomplete, and app.fetch reports block:expense-approval as missing.
See Composing an app.
Options
Context
The menu tells the member what the action sends: “Sends this message”, “Sends this thread”, “Sends this conversation” or “Sends the chat around this”. Ask for the least your action needs.agreed is the conversation’s Agreed statement, or null. Each context message is
{ id, text, author, createdAt }, with plain text of at most 2,000 characters, and the newest
messages are kept within a budget of 32,000 characters.
src/summarize.tsx
context is typed by what you declare: an action declared with "thread" can receive the message or
thread levels, never the conversation. Always check context.level. An install that hasn’t approved
a wider context yet still runs the version that asked for less, and receives that narrower level.
Wider context needs approval
Asking for more context is an access change. Moving an action from"message" to "thread", or to
"conversation", makes installs stay on their current version until a workspace admin approves the
new access, and your app receives app.reconsentRequired. reintersect check --app warns about it
before you deploy (access-widened). Asking for less never needs approval. See
Publishing new versions.
Handler context
Answers
A message action answers exactly like a slash command:- Public
- Private
- Notice only
Timing
Reintersect waits up to 30 seconds for an answer and doesn’t retry. For slower work,defer, exactly
as for commands:
{ visibility: "public" } as the second argument, as above, to show it to everyone who can see the
message. It’s opt-in because the row shows which action ran. The answer keeps its own visibility
either way.
You have 15 minutes to answer through
POST /v0/invocations/respond, which defer and
reintersect.invocations.respond call for you. If the deferred task throws or fails, the SDK answers
with a generic private danger notice so the member isn’t left waiting. Catch the failure inside the
task to answer your own way.
Who sees the item
Message actions appear on circle chat messages, posts and replies, and direct messages, for members who can see the message, in workspaces where the app is installed. A development install shows its message actions only to its developer. Message actions aren’t available in circles connected to another workspace or a Slack channel. Running a message action in a private circle invites your app to that circle, so it can reply there and receive that circle’s events afterwards.Over the wire
Without the SDK, a message action arrives as amessageAction.run delivery with
{ id, message, context, surface, invocationId, interactionToken }, and your endpoint answers 200
with { visibility, content?, block?: { type, props }, notice? }, or 202 with { visibility } (who
sees your app thinking: "public" or "private") and answers later. See the delivery protocol.