Implement Request/Reply in an AsyncAPI document for a Slack app

Found an error? Have a suggestion?Edit this page on GitHub

Introduction

In the Create an AsyncAPI Document for a Slackbot with WebSockets tutorial, you learned how to write an AsyncAPI document for a Slackbot Heart-Counter that actively monitored reactions associated with a message. In this lesson, let's go a step further. After receiving a reaction, Heart-Counter responds via a message back to the Slack server through WebSocket to confirm the event reception.

The interaction where the Slackbot acknowledges the event and replies with a specific response sets the stage for the Request/Reply messaging pattern discussed in this context.

Refer to the Request/Reply pattern tutorial for an introduction to its implementation.

Background context

The Request-Reply Messaging Pattern in AsyncAPI is an exciting and highly anticipated feature. The messaging pattern mirrors a traditional conversation, where one "requester" entity initiates a query or request, and the "responder" entity provides a specific and expected response. The messaging pattern can work in both synchronous and asynchronous environments and is very beneficial to decouple components by allowing them to operate independently in a distributed system.

Define messages

In the Heart-Counter tutorial, you dealt with the hello event triggered when the WebSocket connection was established and the reaction event expected when a new reaction-added event was triggered.

In this tutorial, you'll add the acknowledge message to your AsyncAPI document to represent the acknowledgment sent by the Slack application back to the server to indicate that it has successfully received the message.

1components:
2messages:
3  reaction:
4    summary: Action triggered when the channel receives a new reaction-added event
5    payload:
6      $ref: '#/components/schemas/reaction'
7  hello:
8    summary: Action triggered when a successful WebSocket connection is established
9    payload:
10      $ref: '#/components/schemas/hello'
11  acknowledge:
12    summary: Acknowledgement response sent to Server
13    payload:
14      $ref: '#/components/schemas/acknowledge' 

Define schemas

Previously, the reaction schema was simplified to include the event payload. However, in this instance, you will be able to elaborate on the schema for the complete request it is expected to receive.

Remember

The sample request and response payloads are extracted from Slack's official documentation.

1  schemas:
2  hello:
3    type: object
4    properties:
5      type:
6        type: string
7        description: A hello string confirming WebSocket connection
8      connection_info:
9        type: object
10        properties:
11          app_id:
12            type: string
13      num_connections:
14        type: integer
15      debug_info:
16        type: object
17        properties:
18          host:
19            type: string
20          started:
21            type: string
22          build_number:
23            type: integer
24          approximate_connection_time:
25            type: integer
26  reaction:
27    type: object
28    properties:
29      envelope_id:
30        type: string
31        description: 'Unique ID assigned to payload'
32      payload:
33        type: object
34        description: 'Payload of the reaction added event'
35        properties:
36          token:
37            type: string
38          team_id:
39            type: string
40          event:
41            type: object
42            properties:
43              user:
44                type: string
45                description: User ID who performed this event
46              reaction:
47                type: string
48                description: The only reaction that you need is a heart emoji
49              item_user:
50                type: string
51                description: |
52                  User ID that created the original item that has been reacted
53                  to
54              item:
55                type: object
56                properties:
57                  channel:
58                    type: string
59                    description: Channel information of original message
60                  ts:
61                    type: string
62                    description: Timestamp information of original message
63              event_ts:
64                type: string
65                description: Reaction timestamp
66      type:
67        type: string
68      accepts_response_payload:
69        type: boolean 

Additionally, you will also be adding the acknowledge schema that makes use of the envelope_id attribute to send a reply back to Slack acknowledging that event has been received.

1    acknowledge:
2    type: object
3    properties:
4      envelope_id:
5        type: string
6        description: 'Unique ID of acknowledged payload'
7      payload:
8        type: object
9        description: 'Optional payload of event' 

Define acknowledge message to channel

Extend the channel the Heart-Counter used to include the acknowledge message.

1channels:
2root:
3  address: /
4  messages:
5    hello:
6      $ref: '#/components/messages/hello'
7    reaction:
8      $ref: '#/components/messages/reaction'
9    acknowledge:
10      $ref: '#/components/messages/acknowledge' 

Define operations

Now you've reached the most important part of the tutorial; it's time to represent the Request/Reply pattern.

Both helloListener and reactionListener operations are set to receive events. However, in the case of reactionListener, you also want to represent the message sent back to the server. This is where the reply attribute comes into play.

Since both the request and reply function happens over the same WebSocket URL, both channel values stay the same. However, you can differentiate each operation's message by specifying the messages sent or received. Thus, you can say that for a reaction message received over the root channel, the reactionListener operation will reply with the acknowledge message over the same channel.

1operations:
2helloListener:
3  action: receive
4  channel:
5    $ref: '#/channels/root'
6  messages:
7    - $ref: '#/channels/root/messages/hello'
8reactionListener:
9  action: receive
10  channel: 
11    $ref: '#/channels/root'
12  messages:
13    - $ref: '#/channels/root/messages/reaction'
14  reply:
15    messages:
16      - $ref: '#/channels/root/messages/acknowledge'      
17    channel: 
18      $ref: '#/channels/root' 

Putting all this together, you have your AsyncAPI document ready to go!

1asyncapi: 3.0.0
2info:
3title: Implement Request/Reply in an AsyncAPI document for a Slack app
4version: 1.0.0
5description: >
6  The Heart-Counter manages popular messages in a Slack workspace by
7  monitoring message reaction data. It also sends an acknowledgment message
8  back to the Slack Server to indicate it has received the message.
9servers:
10production:
11  host: wss-primary.slack.com
12  pathname: /link
13  protocol: wss
14  description: Slack's server in Socket Mode for real-time communication
15channels:
16root:
17  address: /
18  messages:
19    hello:
20      $ref: '#/components/messages/hello'
21    reaction:
22      $ref: '#/components/messages/reaction'
23    acknowledge:
24      $ref: '#/components/messages/acknowledge'
25  bindings:
26    ws:
27      query:
28        type: object
29        description: >-
30          Tokens are produced in the WebSocket URL generated from the
31          [apps.connections.open](https://api.slack.com/methods/apps.connections.open)
32          method from Slack's API
33        properties:
34          ticket:
35            type: string
36            description: Temporary token generated when connection is initiated
37            const: 13748dac-b866-4ea7-b98e-4fb7895c0a7f
38          app_id:
39            type: string
40            description: Unique identifier assigned to the Slack app
41            const: fe684dfa62159c6ac646beeac31c8f4ef415e4f39c626c2dbd1530e3a690892f
42operations:
43helloListener:
44  action: receive
45  channel:
46    $ref: '#/channels/root'
47  messages:
48    - $ref: '#/channels/root/messages/hello'
49reactionListener:
50  action: receive
51  channel:
52    $ref: '#/channels/root'
53  messages:
54    - $ref: '#/channels/root/messages/reaction'
55  reply:
56    messages:
57      - $ref: '#/channels/root/messages/acknowledge'
58    channel:
59      $ref: '#/channels/root'
60components:
61messages:
62  reaction:
63    summary: Action triggered when the channel receives a new reaction-added event
64    payload:
65      $ref: '#/components/schemas/reaction'
66  hello:
67    summary: Action triggered when a successful WebSocket connection is established
68    payload:
69      $ref: '#/components/schemas/hello'
70  acknowledge:
71    summary: Acknowledgement response sent to Server
72    payload:
73      $ref: '#/components/schemas/acknowledge'
74schemas:
75  hello:
76    type: object
77    properties:
78      type:
79        type: string
80        description: A hello string confirming WebSocket connection
81      connection_info:
82        type: object
83        properties:
84          app_id:
85            type: string
86      num_connections:
87        type: integer
88      debug_info:
89        type: object
90        properties:
91          host:
92            type: string
93          started:
94            type: string
95          build_number:
96            type: integer
97          approximate_connection_time:
98            type: integer
99  reaction:
100    type: object
101    properties:
102      envelope_id:
103        type: string
104        description: 'Unique ID assigned to payload'
105      payload:
106        type: object
107        description: 'Payload of the reaction added event'
108        properties:
109          token:
110            type: string
111          team_id:
112            type: string
113          event:
114            type: object
115            properties:
116              user:
117                type: string
118                description: User ID who performed this event
119              reaction:
120                type: string
121                description: The only reaction that you need is a heart emoji
122              item_user:
123                type: string
124                description: |
125                  User ID that created the original item that has been reacted
126                  to
127              item:
128                type: object
129                properties:
130                  channel:
131                    type: string
132                    description: Channel information of original message
133                  ts:
134                    type: string
135                    description: Timestamp information of original message
136              event_ts:
137                type: string
138                description: Reaction timestamp
139      type:
140        type: string
141      accepts_response_payload:
142        type: boolean
143  acknowledge:
144    type: object
145    properties:
146      envelope_id:
147        type: string
148        description: 'Unique ID of acknowledged payload'
149      payload:
150        type: object
151        description: 'Optional payload of event' 

Summary

Great job getting to the end! In this tutorial, you learned how to create an AsyncAPI document for a use case that implemented the Request-Reply messaging pattern. Now, you can explore this pattern with sub-patterns to see how it works with real-life use cases.

Was this helpful?
Help us improve the docs by adding your contribution.
OR
Github:AsyncAPICreate Issue on GitHub