Register and Dispatch an Action

Slack provides a web API that allows applications to invoke RPC-style methods to read and write data in Slack. The Slack namespace provides access to these web APIs by obtaining a Slack client and enabling you to post messages or work with reactions etc.

Register an Action 

To register an action with an app, use the SlackApp metadata definition. The .slackapp file must have at least two properties.

  • description—A brief description of the action.
  • action—The location of the action.
  • To register an action for commands and shortcuts, use the commands, globalShortcuts, and messageShortcuts properties.
description: End to End Apex Example App
commands:
  /apex-create-record:
    action:
      definition: apex__action__CreateRecordCommandDispatcher
    title: Create Record Command
    description: Create a record using a slack command.
globalShortcuts:
  apex-create-record-global:
    action:
      definition: apex__action__CreateRecordShortcutDispatcher
    title: Create Record Global Shortcut
    description: Create a record using a slack global shortcut.
messageShortcuts:
  apex-create-record-message:
    action:
      definition: apex__action__CreateRecordShortcutDispatcher
    title: Create Record Message Shortcut
    description: Create a record using a slack message shortcut.

In the ViewDefinition metadata, use an action address to associate an event with an action. To build an action address, use the apex__action__ClassName or apex__action__Namespace.ClassName format. See App Configuration Keys.

Dispatch an Action 

The action system comprises two phases, insulating the app from dealing with the timeouts Slack imposes for HTTP responses.

Phase 1: Dispatching 

In the dispatching phase, the action determines how it reacts to the request.

The action must decide how to handle the request. It must choose which of these types of responses it wants to use based on the inputs to the action.

  • Ack: The action executes some arbitrary logic but doesn’t have to inform Slack of anything in particular about that logic.
  • Open a modal: The action opens a modal view.
  • Push a modal: The action pushes a modal view on to the existing modal view stack from which the request action originated.
  • Update a modal: The action updates the current modal view from which the request action originated.
  • Clear modal: The action closes the current modal view and clears the entire view stack.

Phase 2: Handling 

In the handling phase, the action determines the details of how to react to the request. The action can run any logic it wants, send requests over the network, query or update a database, or run process-intensive operations. This phase can take as much time as necessary because it isn’t susceptible to the initial HTTP request timeout or a trigger_id timeout based on the dispatching phase's logic.

Avoid expensive operations in the dispatching phase, such as database queries, calls to one of the provided Slack clients, or other network requests. Defer all such activity to the handling phase when possible.

Note

Get Access to a Slack Context and Slack Client 

An action can be bound directly in a Slack runtime context, such as:

  1. An event handler in a declarative component.
  2. A handler in Slack application metadata for commands, shortcuts, and events.

Access Slack Context 

An instance of RequestContext is passed to the invoke() method, which describes the context in which a particular Slack action is invoked.

The invoke() method is available via these dispatcher classes.

The context exposes information about the source of the action in Slack, performs custom logic, and obtains the correct Slack client to respond to Slack based on the request. For example, you can respond to a slash command in the Slack app by extending Slack.SlashCommandDispatcher.

public class ViewRecordCommandDispatcher extends Slack.SlashCommandDispatcher {
  public override Slack.ActionHandler invoke(Slack.SlashCommandParameters parameters, Slack.RequestContext context) {
      return Slack.ActionHandler.modal(new Handler(parameters, context));
  }
  // Set up Handler and update modal
  // or do something else
}

Each action type receives different information in its RequestContext. Here's a summary of the RequestContext class.

global class RequestContext {

    String appId;
    String enterpriseId;
    String teamId;
    String channelId;
    String triggerId;
    String userId;
    Map<String, Object> formData;
    ActionPayload actionPayload;
    MessageContext messageContext;
    ViewContext viewContext;
}

Access a Slack Client 

To respond to a request from Slack, obtain the appropriate client to interact with Slack's web API. Use the App class to obtain a Slack client.

  • getAppClient()—Gets a client to invoke Slack web API methods as the application in this context.
  • getBotClientForTeam(String teamId)—Gets a client to invoke Slack web API methods as the application's bot user in this context for the workspace.
  • getUserClientForTeam(String teamId, String slackUserId)—Gets a client to invoke Slack web API methods as the user in this context.

Example 

This example calls the getBotClientForTeam() method and posts a message using ChatPostMessageRequest, which is an Apex wrapper for Slack's chat.postMessage API method. It assumes that you created a SlackApp and ViewDefinition metadata definition and authorized the app.

public class ClientTest {
    public static void run() {

        // Replace with your own values
        String teamId = 'Txxxx';
        String enterpriseId = 'xxxx';
        String channelId = 'Dxxxx';
        String userId = 'Uxxxx';
        String adminUserId = 'Uxxxx';
        String text = 'Hello from Apex!';

        Slack.App app = Slack.App.ExampleIsvApp.get();
        Slack.BotClient client = app.getBotClientForTeam(teamId);

        // Post a message
        Slack.ViewReference view = Slack.View.message_withblocks.get();
        view.setParameter('text', 'Hello from apex');
        Slack.ChatPostMessageRequest req = new Slack.ChatPostMessageRequest.builder()
            .channel(channelId)
            .viewReference(view)
            .build();

        Slack.ChatPostMessageResponse response = client.chatPostMessage(req);
        System.debug('response: ' + response.isOk());
        System.debug('error: ' + response.getError());
    }
}

See Also 

Create an Apex Handler

Beta Feature

This feature is not generally available. It is not part of your purchased Services. This feature is subject to change, may be discontinued with no notice at any time in SFDC’s sole discretion, and SFDC may never make this feature generally available. Make your purchase decisions only on the basis of generally available products and features. This feature is made available on an AS IS basis and use of this feature is at your sole risk.