From c00367c11faa6cc213308c817ac2419173910fcd Mon Sep 17 00:00:00 2001 From: Tracy Rericha Date: Thu, 6 Feb 2025 09:18:09 -0500 Subject: [PATCH 1/3] restructure --- docs/content/guides/assistants.md | 173 ++++++++++++++++-- docs/content/guides/events-api.md | 2 +- .../getting-started-with-bolt-socket-mode.md | 2 +- .../guides/getting-started-with-bolt.md | 2 +- docs/content/guides/rtm.md | 9 +- docs/content/guides/steps-from-apps.md | 30 +-- docs/content/guides/web-api-basics.md | 2 +- docs/sidebars.js | 96 +++++----- 8 files changed, 231 insertions(+), 85 deletions(-) diff --git a/docs/content/guides/assistants.md b/docs/content/guides/assistants.md index 034c0003d..0c83ed79d 100644 --- a/docs/content/guides/assistants.md +++ b/docs/content/guides/assistants.md @@ -1,20 +1,37 @@ --- +title: Agents & Assistants lang: en --- -# Agents & Assistants +:::info This feature requires a paid plan -This guide focuses on how to implement Agents & Assistants using Bolt. For general information about the feature, please refer to the [API documentation](https://api.slack.com/docs/apps/ai). +If you don't have a paid workspace for development, you can join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. -## Slack App Configuration +::: -To get started, you'll need to enable the **Agents & Assistants** feature on [the app configuration page](https://api.slack.com/apps). Then, add [`assistant:write`](https://api.slack.com/scopes/assistant:write), [`chat:write`](https://api.slack.com/scopes/chat:write), and [`im:history`](https://api.slack.com/scopes/im:history) to the **bot** scopes on the **OAuth & Permissions** page. Also, make sure to subscribe to [`assistant_thread_started`](https://api.slack.com/events/assistant_thread_started), [`assistant_thread_context_changed`](https://api.slack.com/events/assistant_thread_context_changed), and [`message.im`](https://api.slack.com/events/message.im) events on the **Event Subscriptions** page. +Agents and assistants comprise a new messaging experience for Slack. If you're unfamiliar with using agents and assistants within Slack, you'll want to read the [API documentation on the subject](https://api.slack.com/docs/apps/ai). Then come back here to implement them with Bolt! -Please note that this feature requires a paid plan. If you don't have a paid workspace for development, you can join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. +## Configuring your app to support assistants {#configuring-your-app} -## Examples +1. Within [App Settings](https://api.slack.com/apps), enable the **Agents & Assistants** feature. -To handle assistant thread interactions with humans, although you can implement your agents using `app.event(...)` listeners for `assistant_thread_started`, `assistant_thread_context_changed`, and `message` events, Bolt offers a simpler approach. You just need to create an `Assistant` instance, attach the needed event handlers to it, and then add the assistant to your `App` instance. +2. Within the App Settings **OAuth & Permissions** page, add the following scopes: + * [`assistant:write`](https://api.slack.com/scopes/assistant:write) + * [`chat:write`](https://api.slack.com/scopes/chat:write) + * [`im:history`](https://api.slack.com/scopes/im:history) + +3. Within the App Settings **Event Subscriptions** page, subscribe to the following events: + * [`assistant_thread_started`](https://api.slack.com/events/assistant_thread_started) + * [`assistant_thread_context_changed`](https://api.slack.com/events/assistant_thread_context_changed) + * [`message.im`](https://api.slack.com/events/message.im) + +## The `Assistant` class instance {#assistant-class} + +The [`Assistant`](/reference#the-assistantconfig-configuration-object) class can be used to handle the incoming events expected from a user interacting with an assistant in Slack. A typical flow would look like: + +1. [The user starts a thread](#handling-a-new-thread). The `Assistant` class handles the incoming [`assistant_thread_started`](https://api.slack.com/events/assistant_thread_started) event. +2. [The thread context may change at any point](#handling-thread-context-changes). The `Assistant` class can handle any incoming [`assistant_thread_context_changed`](https://api.slack.com/events/assistant_thread_context_changed) events. The class also provides a default `context` store to keep track of thread context changes as the user moves through Slack. +3. [The user responds](#handling-user-response). The `Assistant` class handles the incoming [`message.im`](https://api.slack.com/events/message.im) event. ```java App app = new App(); @@ -54,29 +71,29 @@ assistant.userMessage((req, ctx) -> { app.assistant(assistant); ``` -When a user opens an Assistant thread while in a channel, the channel information is stored as the thread's `AssistantThreadContext` data. You can access this information by using the `get_thread_context` utility. The reason Bolt provides this utility is that the most recent thread context information is not included in the subsequent user message event payload data. Therefore, an app must store the context data when it is changed so that the app can refer to the data in message event listeners. +While the `assistant_thread_started` and `assistant_thread_context_changed` events do provide Slack-client thread context information, the `message.im` event does not. Any subsequent user message events won't contain thread context data. For that reason, Bolt not only provides a way to store thread context — the `threadContextStore` property — but it also provides a `DefaultThreadContextStore` instance that is utilized by default. This implementation relies on storing and retrieving [message metadata](https://api.slack.com/metadata/using) as the user interacts with the assistant. -When the user switches channels, the `assistant_thread_context_changed` event will be sent to your app. If you use the built-in `Assistant` middleware without any custom configuration (like the above code snippet does), the updated context data is automatically saved as message metadata of the first reply from the assistant bot. +If you do provide your own `threadContextStore` property, it must feature `get` and `save` methods. -As long as you use the built-in approach, you don't need to store the context data within a datastore. The downside of this default behavior is the overhead of additional calls to the Slack API. These calls include those to `conversations.history` which are used to look up the stored message metadata that contains the thread context (via `context.getThreadContextService().findCurrentContext(channelId, threadTs)`). +:::tip +Be sure to give the [assistants reference docs](/reference#agents--assistants) a look! +::: -If you prefer storing this data elsewhere, you can pass your own `AssistantThreadContextService` implementation to the `Assistant` instance: +## Handling a new thread {#handling-a-new-thread} -```java -Assistant assistant = new Assistant(new YourOwnAssistantThreadContextService()); -``` +When the user opens a new thread with your assistant, the [`assistant_thread_started`](https://api.slack.com/events/assistant_thread_started) event will be sent to your app. -
+:::tip +When a user opens an assistant thread while in a channel, the channel info is stored as the thread's `AssistantThreadContext` data. You can grab that info by using the `get_thread_context` utility, as subsequent user message event payloads won't include the channel info. +::: - -Block Kit interactions in the assistant thread - +### Block Kit interactions in the assistant thread {#block-kit-interactions} For advanced use cases, Block Kit buttons may be used instead of suggested prompts, as well as the sending of messages with structured [metadata](https://api.slack.com/metadata) to trigger subsequent interactions with the user. For example, an app can display a button like "Summarize the referring channel" in the initial reply. When the user clicks the button and submits detailed information (such as the number of messages, days to check, the purpose of the summary, etc.), the app can handle that information and post a message that describes the request with structured metadata. -By default, your app can't respond to its own bot messages (Bolt prevents infinite loops by default). However, if you set `ignoringSelfAssistantMessageEventsEnabled` to false and add a `botMessage` listener to your `Assistant` middleware, your app can continue processing the request as shown below: +By default, apps can't respond to their own bot messages (Bolt prevents infinite loops by default). However, if you set `ignoringSelfAssistantMessageEventsEnabled` to false and add a `botMessage` listener to your `Assistant` middleware, your app can continue processing the request as shown below: ```java App app = new App(AppConfig.builder() @@ -156,4 +173,120 @@ assistant.userMessage((req, ctx) -> { app.assistant(assistant); ``` -
+## Handling thread context changes {#handling-thread-context-changes} + +When the user switches channels, the [`assistant_thread_context_changed`](https://api.slack.com/events/assistant_thread_context_changed) event will be sent to your app. + +If you use the built-in `Assistant` middleware without any custom configuration, the updated context data is automatically saved as [message metadata](https://api.slack.com/metadata/using) of the first reply from the assistant bot. + +As long as you use the built-in approach, you don't need to store the context data within a datastore. The downside of this default behavior is the overhead of additional calls to the Slack API. These calls include those to `conversations.history`, which are used to look up the stored message metadata that contains the thread context (via `context.getThreadContextService().findCurrentContext(channelId, threadTs)`). + +If you prefer storing this data elsewhere, you can pass your own custom `AssistantThreadContextStore` implementation to the `Assistant` constructor. We provide `FileAssistantThreadContextStore`, which is a reference implementation that uses the local file system. Since this reference implementation relies on local files, it's not advised for use in production. For production apps, we recommend creating a class that inherits `AssistantThreadContextStore`. + +```java +Assistant assistant = new Assistant(new YourOwnAssistantThreadContextService()); +``` + +## Handling the user response {#handling-user-response} + +When the user messages your assistant, the [`message.im`](https://api.slack.com/events/message.im) event will be sent to your app. + +Messages sent to the assistant do not contain a [subtype](https://api.slack.com/events/message#subtypes) and must be deduced based on their shape and any provided [message metadata](https://api.slack.com/metadata/using). + +There are three utilities that are particularly useful in curating the user experience: +* [`say`](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/#slack_bolt.Say) +* [`setTitle`](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/#slack_bolt.SetTitle) +* [`setStatus`](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/#slack_bolt.SetStatus) + +## Full example: Assistant Simple App {#full-example} + +Below is the `AssistantSimpleApp.java` file of the [Assistant Template repo](https://github.com/slackapi/java-slack-sdk/tree/d29a29afff9f2a518495d618502cb7b292e2eb14/bolt-socket-mode/src/test/java/samples) we've created for you to build off of. + +```java +package samples; + +import com.slack.api.bolt.App; +import com.slack.api.bolt.AppConfig; +import com.slack.api.bolt.middleware.builtin.Assistant; +import com.slack.api.bolt.socket_mode.SocketModeApp; +import com.slack.api.model.assistant.SuggestedPrompt; +import com.slack.api.model.event.AppMentionEvent; +import com.slack.api.model.event.MessageEvent; + +import java.util.Collections; + +public class AssistantSimpleApp { + + public static void main(String[] args) throws Exception { + String botToken = System.getenv("SLACK_BOT_TOKEN"); + String appToken = System.getenv("SLACK_APP_TOKEN"); + + App app = new App(AppConfig.builder().singleTeamBotToken(botToken).build()); + + Assistant assistant = new Assistant(app.executorService()); + + assistant.threadStarted((req, ctx) -> { + try { + ctx.say("Hi, how can I help you today?"); + ctx.setSuggestedPrompts(r -> r + .title("Select one of the following:") // optional + .prompts(Collections.singletonList(SuggestedPrompt.create("What does SLACK stand for?"))) + ); + } catch (Exception e) { + ctx.logger.error("Failed to handle assistant thread started event: {e}", e); + } + }); + + assistant.userMessage((req, ctx) -> { + try { + // ctx.setStatus(r -> r.status("is typing...")); works too + ctx.setStatus("is typing..."); + Thread.sleep(500L); + if (ctx.getThreadContext() != null) { + String contextChannel = ctx.getThreadContext().getChannelId(); + ctx.say("I am ware of the channel context: <#" + contextChannel + ">"); + } else { + ctx.say("Here you are!"); + } + } catch (Exception e) { + ctx.logger.error("Failed to handle assistant user message event: {e}", e); + try { + ctx.say(":warning: Sorry, something went wrong during processing your request!"); + } catch (Exception ee) { + ctx.logger.error("Failed to inform the error to the end-user: {ee}", ee); + } + } + }); + + assistant.userMessageWithFiles((req, ctx) -> { + try { + ctx.setStatus("is analyzing the files..."); + Thread.sleep(500L); + ctx.setStatus("is still checking the files..."); + Thread.sleep(500L); + ctx.say("Your files do not have any issues!"); + } catch (Exception e) { + ctx.logger.error("Failed to handle assistant user message event: {e}", e); + try { + ctx.say(":warning: Sorry, something went wrong during processing your request!"); + } catch (Exception ee) { + ctx.logger.error("Failed to inform the error to the end-user: {ee}", ee); + } + } + }); + + app.use(assistant); + + app.event(MessageEvent.class, (req, ctx) -> { + return ctx.ack(); + }); + + app.event(AppMentionEvent.class, (req, ctx) -> { + ctx.say("You can help you at our 1:1 DM!"); + return ctx.ack(); + }); + + new SocketModeApp(appToken, app).start(); + } +} +``` diff --git a/docs/content/guides/events-api.md b/docs/content/guides/events-api.md index ba244bc12..6653d2267 100644 --- a/docs/content/guides/events-api.md +++ b/docs/content/guides/events-api.md @@ -2,7 +2,7 @@ lang: en --- -# Events API +# Events The [Events API](https://api.slack.com/events-api) is a streamlined way to build apps and bots that respond to activities in Slack. All you need is a Slack app and a secure place for us to send your events. diff --git a/docs/content/guides/getting-started-with-bolt-socket-mode.md b/docs/content/guides/getting-started-with-bolt-socket-mode.md index 55c2c3d0c..6abbd0383 100644 --- a/docs/content/guides/getting-started-with-bolt-socket-mode.md +++ b/docs/content/guides/getting-started-with-bolt-socket-mode.md @@ -2,7 +2,7 @@ lang: en --- -# Getting Started with Bolt (Socket Mode) +# Socket Mode **Bolt for Java** is a framework on the JVM that offers an abstraction layer to build Slack apps quickly using modern platform features. diff --git a/docs/content/guides/getting-started-with-bolt.md b/docs/content/guides/getting-started-with-bolt.md index e3cfb788f..dff7a098b 100644 --- a/docs/content/guides/getting-started-with-bolt.md +++ b/docs/content/guides/getting-started-with-bolt.md @@ -2,7 +2,7 @@ lang: en --- -# Getting Started with Bolt +# Getting Started with Bolt for Java **Bolt for Java** is a framework on the JVM that offers an abstraction layer to build Slack apps quickly using modern platform features. diff --git a/docs/content/guides/rtm.md b/docs/content/guides/rtm.md index 091badc48..07dc14bcb 100644 --- a/docs/content/guides/rtm.md +++ b/docs/content/guides/rtm.md @@ -4,17 +4,18 @@ lang: en # Real Time Messaging (RTM) -[The Real Time Messaging API](https://api.slack.com/rtm) is a WebSocket-based API that allows you to receive events from Slack in real-time and send messages as users. It's sometimes referred to just as the "RTM API". +:::danger -:::danger +RTM is a deprecated feature and is no longer available for modern scoped apps. -RTM isn't available for modern scoped apps anymore. We recommend using the [Events API](/guides/events-api) and [Web API](/guides/web-api-basics) instead. If you need to use RTM (possibly due to corporate firewall limitations), you can do so by creating a legacy scoped app. If you have an existing RTM app, do not update its scopes as it will be updated to a modern scoped app and stop working with RTM. +We recommend using the [Events API](/guides/events-api) and [Web API](/guides/web-api-basics) instead. If you need to use RTM (possibly due to corporate firewall limitations), you can do so by creating a legacy scoped app. If you have an existing RTM app, do not update its scopes as it will be updated to a modern scoped app and stop working with RTM. ::: ---- ## Prerequisites +[The Real Time Messaging API](https://api.slack.com/rtm) is a WebSocket-based API that allows you to receive events from Slack in real-time and send messages as users. + To use the RTM Client, in addition to the `slack-api-client` library, `javax.websocket-api` and `tyrus-standalone-client (1.x)` are required. Here is a minimum Maven settings file. ```xml diff --git a/docs/content/guides/steps-from-apps.md b/docs/content/guides/steps-from-apps.md index d05ce14b0..2b32e645a 100644 --- a/docs/content/guides/steps-from-apps.md +++ b/docs/content/guides/steps-from-apps.md @@ -2,27 +2,33 @@ lang: en --- -# Workflow Steps from Apps (Deprecated) +# Steps from apps :::danger -Steps from Apps for legacy workflows are now deprecated. Use [new custom steps](https://api.slack.com/automation/functions/custom-bolt). +Steps from Apps is a deprecated feature. + +Steps from Apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as [custom steps for Bolt](https://api.slack.com/automation/functions/custom-bolt). + +Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. ::: -Workflow Steps from apps allow your app to create and process custom workflow steps that users can add using [Workflow Builder](https://api.slack.com/workflows). +Steps from apps allow your app to create and process steps that users can add using [Workflow Builder](https://api.slack.com/workflows). -A workflow step is made up of three distinct user events: +A step is made up of three distinct user events: * Adding or editing the step in a Workflow * Saving or updating the step's configuration * The end user's execution of the step -All three events must be handled for a workflow step to function. Read more about workflow steps from apps in the [API documentation](https://api.slack.com/workflows/steps). +All three events must be handled for a workflow step to function. + +Read more about steps from apps in the [API documentation](https://api.slack.com/workflows/steps). ### Slack App Configuration -To enable Workflow Steps, visit the [Slack App configuration page](http://api.slack.com/apps), choose the app you're working on, and go to **Features** > **Workflow Steps** on the left pane. There are three things to do on the page. +To enable steps from apps, visit the [Slack App configuration page](http://api.slack.com/apps), choose the app you're working on, and go to **Features** > **Workflow Steps** on the left pane. There are three things to do on the page. * Turn on the feature (**Turn on workflow steps**) * Click the **Add Step** button and set the name and Callback ID @@ -30,9 +36,9 @@ To enable Workflow Steps, visit the [Slack App configuration page](http://api.sl Also, your app requires the **Interactivity**. Go to [Interactive Components](/guides/interactive-components) and set the Request URL to receive events from Slack. --- -## Creating workflow steps +## Creating steps from apps -To create a workflow step, Bolt provides the `WorkflowStep` class. +To create a step from app, Bolt provides the `WorkflowStep` class. When instantiating a new `WorkflowStep`, pass in the step's `callback_id` and a configuration object. @@ -58,11 +64,11 @@ app.step(step); ``` --- -## Adding or editing workflow steps +## Adding or editing steps from apps When a builder adds (or later edits) your step in their workflow, your app will receive a [`workflow_step_edit`](https://api.slack.com/reference/workflows/workflow_step_edit) event. The `edit` callback in your `WorkflowStep` configuration will be run when this event is received. -Whether a builder is adding or editing a step, you need to send them a [workflow step configuration modal](https://api.slack.com/reference/workflows/configuration-view). This modal is where step-specific settings are chosen, and it has more restrictions than typical modals—most notably, it cannot include `title`, `submit`, or `close` properties. By default, the configuration modal's `callback_id` will be the same as the workflow step. +Whether a builder is adding or editing a step, you need to send them a [step from app configuration modal](https://api.slack.com/reference/workflows/configuration-view). This modal is where step-specific settings are chosen, and it has more restrictions than typical modals—most notably, it cannot include `title`, `submit`, or `close` properties. By default, the configuration modal's `callback_id` will be the same as the workflow step. Within the `edit` callback, the `configure()` utility can be used to easily open your step's configuration modal by passing in an object with your view's `blocks`. To disable saving the configuration before certain conditions are met, pass in `submit_disabled` with a value of `true`. @@ -150,11 +156,11 @@ app.step(step); ``` --- -## Executing workflow steps +## Executing steps from apps When your workflow step is executed by an end user, your app will receive a [`workflow_step_execute`](https://api.slack.com/events/workflow_step_execute) event. The `execute` callback in your `WorkflowStep` configuration will be run when this event is received. -Using the `inputs` from the `save` callback, this is where you can make third-party API calls, save information to a database, update the user's Home tab, or decide the outputs that will be available to subsequent workflow steps by mapping values to the `outputs` object. +Using the `inputs` from the `save` callback, this is where you can make third-party API calls, save information to a database, update the user's Home tab, or decide the outputs that will be available to subsequent steps from apps by mapping values to the `outputs` object. Within the `execute` callback, your app must either call `complete()` to indicate that the step's execution was successful, or `fail()` to indicate that the step's execution failed. diff --git a/docs/content/guides/web-api-basics.md b/docs/content/guides/web-api-basics.md index 549871877..25b3d4b7e 100644 --- a/docs/content/guides/web-api-basics.md +++ b/docs/content/guides/web-api-basics.md @@ -2,7 +2,7 @@ lang: en --- -# API Client Basics +# Using the Web API `slack-api-client` contains flexibly configurable HTTP clients for making requests to Slack APIs. diff --git a/docs/sidebars.js b/docs/sidebars.js index fa59e3596..8434bd652 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -13,10 +13,6 @@ /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ const sidebars = { - // By default, Docusaurus generates a sidebar from the docs folder structure - // tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], - - // But you can create a sidebar manually sidebarJava: [ { type: 'doc', @@ -24,53 +20,63 @@ const sidebars = { label: 'Java Slack SDK', className: 'sidebar-title', }, - 'guides/getting-started-with-bolt', + { type: 'html', value: '
' }, { type: 'category', - label: 'Bolt for Java', + label: 'Guides', items: [ - 'guides/bolt-basics', - 'guides/socket-mode', - 'guides/assistants', - 'guides/shortcuts', - 'guides/interactive-components', - 'guides/modals', - 'guides/app-home', - 'guides/slash-commands', + { + type: 'category', + label: 'Getting Started', + items: [ + 'guides/getting-started-with-bolt', + 'guides/bolt-basics', + 'guides/supported-web-frameworks', + ], + }, + { + type: 'category', + label: 'Slack API calls', + items: ['guides/composing-messages', 'guides/web-api-basics', 'guides/web-api-client-setup'], + }, 'guides/events-api', - 'guides/steps-from-apps', - 'guides/app-distribution', - 'guides/sign-in-with-slack', - 'guides/supported-web-frameworks', - ], - }, - { - type: 'category', - label: 'Slack API Client', - items: [ - 'guides/web-api-basics', - 'guides/web-api-client-setup', - 'guides/composing-messages', - 'guides/incoming-webhooks', - 'guides/rtm', - ], - }, - { - type: 'category', - label: 'Enterprise', - items: [ - 'guides/web-api-for-admins', - 'guides/scim-api', - 'guides/audit-logs-api' + { + type: 'category', + label: 'App UI & Interactivity', + items: [ + 'guides/interactive-components', + 'guides/shortcuts', + 'guides/modals', + ], + }, + 'guides/assistants', + { + type: 'category', + label: 'App Configuration', + items: [ + 'guides/app-home', + 'guides/socket-mode', + 'guides/slash-commands', + 'guides/incoming-webhooks', + ], + }, + { + type: 'category', + label: 'Authorization & Security', + items: ['guides/app-distribution', 'guides/sign-in-with-slack'], + }, + { + type: 'category', + label: 'Admin Tools', + items: ['guides/web-api-for-admins', 'guides/scim-api', 'guides/audit-logs-api', 'guides/status-api'], + }, + { + type: 'category', + label: 'Legacy', + items: ['guides/steps-from-apps', 'guides/rtm'], + }, ], }, - { - type: 'category', - label: 'Other APIs', - items: [ - 'guides/status-api' - ], - }, {type: 'html', value: '
'}, { type: 'category', From aa0f9a3545808de973a06e24130d5204415a7c0b Mon Sep 17 00:00:00 2001 From: Tracy Rericha Date: Thu, 6 Feb 2025 12:29:01 -0500 Subject: [PATCH 2/3] updates --- .../getting-started-with-bolt-socket-mode.md | 300 ---------------- .../guides/getting-started-with-bolt.md | 329 ++++++++++++++++-- docs/content/index.md | 10 +- docs/sidebars.js | 80 ++--- 4 files changed, 328 insertions(+), 391 deletions(-) delete mode 100644 docs/content/guides/getting-started-with-bolt-socket-mode.md diff --git a/docs/content/guides/getting-started-with-bolt-socket-mode.md b/docs/content/guides/getting-started-with-bolt-socket-mode.md deleted file mode 100644 index 6abbd0383..000000000 --- a/docs/content/guides/getting-started-with-bolt-socket-mode.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -lang: en ---- - -# Socket Mode - -**Bolt for Java** is a framework on the JVM that offers an abstraction layer to build Slack apps quickly using modern platform features. - -This guide explains how to start your first-ever Bolt app. - -If you're not yet familiar with Slack app development in general, we recommend reading the [Slack API docs](https://api.slack.com/docs). - ---- -## Project Setup - -Let's start building a Slack app using Bolt! This guide includes instructions on how to set up a Bolt project with Maven and Gradle, so use whichever section you'd like. - -### Maven - -After you [create your Maven project](https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html), you need to add the `bolt` dependency to your `pom.xml` file. The `bolt` dependency is a framework-agnostic module. To enable [Socket Mode](https://api.slack.com/apis/connections/socket), the `bolt-socket-mode` library and its provided-scope dependencies are also required for your app. - -```xml - - com.slack.api - bolt - sdkLatestVersion - - - com.slack.api - bolt-socket-mode - sdkLatestVersion - - - javax.websocket - javax.websocket-api - javaxWebsocketApiVersion - - - org.glassfish.tyrus.bundles - tyrus-standalone-client - tyrusStandaloneClientVersion - - - org.slf4j - slf4j-simple - slf4jApiVersion - -``` - -By default, the `tyrus-standalone-client` dependency is used as the implementation to manage socket connections in the `bolt-socket-mode` artifact. -If instead you would prefer to use the `Java-WebSocket` implementation, swap its artifact in instead of `tyrus-standalone-client`, and then set `SocketModeClient.Backend.JavaWebSocket` when initializing the client instance: - -```xml - - org.java-websocket - Java-WebSocket - 1.5.1 - -``` - -You will also need to ensure you set the compiler source and target to at least 1.8: - -```xml - - 1.8 - 1.8 - -``` - -### Gradle - -After you [create your Gradle project](https://docs.gradle.org/current/samples/sample_building_java_applications.html), add the `bolt` dependencies to `build.gradle`. - -```groovy -dependencies { - implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") - implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") - implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") - implementation("org.slf4j:slf4j-simple:slf4jApiVersion") -} -``` - ---- -## Run Your Bolt App in 3 Minutes - -### Use `bolt-socket-mode` - -`bolt-socket-mode` is a handy way to start your [Socket Mode](https://api.slack.com/apis/connections/socket) app. It allows developers to build a Slack app backend service by writing only a main method initializes `App` and establishes a WebSocket connection to the Socket Mode servers. - -#### `build.gradle` - -The following build settings should be working as-is. Put it in the root directory of your project. - -```groovy -plugins { - id("application") -} -repositories { - mavenCentral() -} -dependencies { - implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") - implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") - implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") - implementation("org.slf4j:slf4j-simple:slf4jApiVersion") -} -application { - mainClassName = "hello.MyApp" -} -run { - // gradle run -DslackLogLevel=debug - systemProperty "org.slf4j.simpleLogger.log.com.slack.api", System.getProperty("slackLogLevel") -} -``` - -#### `src/main/java/hello/MyApp.java` - -Coding with this framework is much simpler than you think. - -Only single source code is required to run your first-ever Bolt app. All you need to do is define the main method that starts `SocketModeApp`. - -```java -package hello; - -import com.slack.api.bolt.App; -import com.slack.api.bolt.socket_mode.SocketModeApp; - -public class MyApp { - public static void main(String[] args) throws Exception { - // App expects an env variable: SLACK_BOT_TOKEN - App app = new App(); - - app.command("/hello", (req, ctx) -> { - return ctx.ack(":wave: Hello!"); - }); - - // SocketModeApp expects an env variable: SLACK_APP_TOKEN - new SocketModeApp(app).start(); - } -} -``` - -If you go with JDK 10+, thanks to [Local Variable Type Inference](https://developer.oracle.com/java/jdk-10-local-variable-type-inference.html), your code could be much more concise. To take advantage of it, install OpenJDK 11 and set the compatible Java versions in `build.gradle` as below. Also, configure the same on your IDE. - -```groovy -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} -``` - -Now, you don't need to repeat the same type in a single line. - -```java -var app = new App(); -app.command("/hello", (req, ctx) -> { - return ctx.ack(":wave: Hello!"); -}); -new SocketModeApp(app).start(); -``` - -### Start the App with Two Env Variables - -The default constructor expects the following two env variables exist when starting the app. - -|Env Variable|Description| -|-|-| -|`SLACK_BOT_TOKEN`|The valid bot token value starting with `xoxb-` in your development workspace. To issue a bot token, you need to install your Slack App that has a bot user to your development workspace. Visit the [Slack App configuration page](http://api.slack.com/apps), choose the app you're working on, and go to **Settings** > **Install App** on the left pane (Add [`app_mentions:read`](https://api.slack.com/scopes/app_mentions:read) bot scope if you see the message saying "Please add at least one feature or permission scope to install your app.").

If you run an app that is installable for multiple workspaces, no need to specify this. Consult [App Distribution (OAuth)](/guides/app-distribution) for further information instead.| -|`SLACK_APP_TOKEN`|The valid app-level token value starting with `xapp-` for your Slack app. To issue an app-level token, Visit the [Slack App configuration page](http://api.slack.com/apps), choose the app you're working on, and go to **Settings** > **Basic Information** > **App-Level Tokens**, and then create a new one with `connections:write` scope.| - -If you prefer configuring an `App` in a different way, write some code to initialize `AppConfig` on your own. - -Set the two environment variables and run: - -- Gradle users: `gradle run` (for more detailed logging: `gradle run -DslackLogLevel=debug`), -- Maven users: `mvn compile exec:java -Dexec.mainClass="hello.MyApp"` (for more detailed logging you can also provide the `-Dorg.slf4j.simpleLogger.defaultLogLevel=debug` flag) - -The command runs your main method. - -```bash -# Visit https://api.slack.com/apps to know these -export SLACK_BOT_TOKEN=xoxb-...your-own-valid-one -export SLACK_APP_TOKEN=xapp-...your-own-valid-one - -# run the main function -# gradle users should run: -gradle run -# maven users should run: -mvn compile exec:java -Dexec.mainClass="hello.MyApp" -``` - -If you get stuck this setup, go through the following checklist: - -* ✅ JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) -* ✅ Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) -* ✅ `build.gradle` has `bolt-socket-mode` and `tyrus-standalone-client` in the dependencies and valid application plugin settings -* ✅ `src/main/java/hello/MyApp.java` with a class having its main method -* ✅ [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`commands`](https://api.slack.com/scopes/commands) bot scope, add **an app-level token with `connections:write` scope**, and install the app to your development workspace -* ✅ Copy [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**App-Level Token**](https://api.slack.com/docs/token-types#app) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables - -### Enable `/hello` Command - -Your app is up now! However, the slash command `/hello` in the code is still unavailable. To enable it, follow the steps below: - -* Visit [Slack App configuration pages](https://api.slack.com/apps) -* Choose your app -* Go to **Settings** > **Socket Mode** on the left pane - * Turn on **Enable Socket Mode** -* Go to **Features** > **Slash Commands** on the left pane - * Click **Create New Command** button - * Input the command information on the dialog: - * **Command**: `/hello` - * **Short Description**: whatever you like - * Click **Save** Button - -Now you can hit the `/hello` command in your development workspace. If your app is successfully running, the app should respond to the command by replying `👋 Hello!`. - ---- -## Getting Started in Kotlin - -For code simplicity, [Kotlin](https://kotlinlang.org/) language would be a great option for writing Bolt apps. In this section, you'll learn how to set up a Kotlin project for Bolt apps. - -#### `build.gradle` - -Most of the build settings are necessary for enabling Kotlin language. Adding `bolt-socket-mode` && `tyrus-standalone-client` to the dependencies is the only one that is specific to Bolt. - -```groovy -plugins { - id("org.jetbrains.kotlin.jvm") version "kotlinVersion" - id("application") -} -repositories { - mavenCentral() -} -dependencies { - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") - implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") - implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") - implementation("org.slf4j:slf4j-simple:slf4jApiVersion") // or logback-classic -} -application { - mainClassName = "MyAppKt" // add "Kt" suffix for main function source file -} -``` - -If you're already familiar with Kotlin and prefer the Gradle Kotlin DSL, of course, there is nothing stopping you. - -#### `src/main/kotlin/MyApp.kt` - -Here is a minimum source file that just starts a Bolt app on your local machine. - -```kotlin -import com.slack.api.bolt.App -import com.slack.api.bolt.socket_mode.SocketModeApp - -fun main() { - val app = App() - - // Write some code here - - SocketModeApp(app).start() -} -``` - -### Make Sure If It Works - -OK, you should be done. Just in case, here is the checklist: - -* ✅ JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) -* ✅ Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) -* ✅ `build.gradle` with valid Kotlin language settings and `bolt-socket-mode` and `tyrus-standalone-client` in the dependencies -* ✅ `src/main/kotlin/MyApp.kt` with a main method -* ✅ [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`commands`](https://api.slack.com/scopes/commands) bot scope, add **an app-level token with `connections:write` scope**, and install the app to your development workspace -* ✅ Copy [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**App-Level Token**](https://api.slack.com/docs/token-types#app) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables - -If all are ✅, bootstrapping your first-ever Kotlin-flavored Bolt app will succeed. - -```bash -# Visit https://api.slack.com/apps to know these -export SLACK_BOT_TOKEN=xoxb-...your-own-valid-one -export SLACK_APP_TOKEN=xapp-...your-own-valid-one - -# run the main function -gradle run -``` - -From here, all you need to do is write code and restart the app. Enjoy Bolt app development in Kotlin! 👋 - -:::tip - -We strongly recommend using [IntelliJ IDEA](https://www.jetbrains.com/idea/) here even if you don't prefer using IDEs. The IDE is the smoothest way to try Kotlin application development. - -::: - ---- -## Next Steps - -Read the [Bolt Basics](/guides/bolt-basics) page for further information. diff --git a/docs/content/guides/getting-started-with-bolt.md b/docs/content/guides/getting-started-with-bolt.md index dff7a098b..e1d9c3c44 100644 --- a/docs/content/guides/getting-started-with-bolt.md +++ b/docs/content/guides/getting-started-with-bolt.md @@ -1,8 +1,9 @@ --- lang: en +title: Getting Started --- -# Getting Started with Bolt for Java +# Getting Started with Bolt for Java {#getting-started} **Bolt for Java** is a framework on the JVM that offers an abstraction layer to build Slack apps quickly using modern platform features. @@ -11,14 +12,73 @@ This guide explains how to start your first-ever Bolt app. If you're not yet familiar with Slack app development in general, we recommend reading the [Slack API docs](https://api.slack.com/docs). --- -## Project Setup +## Setting up your project {#project-setup} Let's start building a Slack app using Bolt! This guide includes instructions on how to set up a Bolt project with Maven and Gradle, so use whichever section you'd like. -### Maven +### Using Maven {#maven} After you [create your Maven project](https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html), you need to add the `bolt` dependency to your `pom.xml` file. The `bolt` dependency is a framework-agnostic module. If you use Bolt along with [Spring Boot](https://spring.io/projects/spring-boot), [Quarkus (Undertow)](https://quarkus.io/), or any others on top of Servlet environment, the `bolt-servlet` library is required for your app. Adding only `bolt-servlet` also works for you. +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +To enable [Socket Mode](https://api.slack.com/apis/connections/socket), the `bolt-socket-mode` library and its provided-scope dependencies are also required for your app. + +```xml + + com.slack.api + bolt + sdkLatestVersion + + + com.slack.api + bolt-socket-mode + sdkLatestVersion + + + javax.websocket + javax.websocket-api + javaxWebsocketApiVersion + + + org.glassfish.tyrus.bundles + tyrus-standalone-client + tyrusStandaloneClientVersion + + + org.slf4j + slf4j-simple + slf4jApiVersion + +``` + +By default, the `tyrus-standalone-client` dependency is used as the implementation to manage socket connections in the `bolt-socket-mode` artifact. +If instead you would prefer to use the `Java-WebSocket` implementation, swap its artifact in instead of `tyrus-standalone-client`, and then set `SocketModeClient.Backend.JavaWebSocket` when initializing the client instance: + +```xml + + org.java-websocket + Java-WebSocket + 1.5.1 + +``` + +You will also need to ensure you set the compiler source and target to at least 1.8: + +```xml + + 1.8 + 1.8 + +``` + + + + ```xml com.slack.api @@ -56,10 +116,28 @@ You will also need to ensure you set the compiler source and target to at least ``` -### Gradle + + + +### Using Gradle {#gradle} After you [create your Gradle project](https://docs.gradle.org/current/samples/sample_building_java_applications.html), add the `bolt` dependencies to `build.gradle`. + + + +```groovy +dependencies { + implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") + implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") + implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") + implementation("org.slf4j:slf4j-simple:slf4jApiVersion") +} +``` + + + + ```groovy dependencies { implementation("com.slack.api:bolt:sdkLatestVersion") @@ -69,17 +147,62 @@ dependencies { } ``` + + + --- -## Run Your Bolt App in 3 Minutes -### Use `bolt-jetty` +## Running your Bolt app {#running} + + + + +**Using `bolt-socket-mode`** + +`bolt-socket-mode` is a handy way to start your [Socket Mode](https://api.slack.com/apis/connections/socket) app. It allows developers to build a Slack app backend service by writing only a main method initializes `App` and establishes a WebSocket connection to the Socket Mode servers. + + + + +**Using `bolt-jetty`** `bolt-jetty` is a handy way to start your Slack app server. It allows developers to build a Slack app backend service by writing only a main method that initializes `App` and starts an HTTP server. -#### `build.gradle` + + + +**Using `build.gradle`** The following build settings should be working as-is. Put it in the root directory of your project. + + + +```groovy +plugins { + id("application") +} +repositories { + mavenCentral() +} +dependencies { + implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") + implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") + implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") + implementation("org.slf4j:slf4j-simple:slf4jApiVersion") +} +application { + mainClassName = "hello.MyApp" +} +run { + // gradle run -DslackLogLevel=debug + systemProperty "org.slf4j.simpleLogger.log.com.slack.api", System.getProperty("slackLogLevel") +} +``` + + + + ```groovy plugins { id("application") @@ -100,10 +223,61 @@ run { } ``` -#### `src/main/java/hello/MyApp.java` + + + +**Using `src/main/java/hello/MyApp.java`** Coding with this framework is much simpler than you think. + + + +Only single source code is required to run your first-ever Bolt app. All you need to do is define the main method that starts `SocketModeApp`. + +```java +package hello; + +import com.slack.api.bolt.App; +import com.slack.api.bolt.socket_mode.SocketModeApp; + +public class MyApp { + public static void main(String[] args) throws Exception { + // App expects an env variable: SLACK_BOT_TOKEN + App app = new App(); + + app.command("/hello", (req, ctx) -> { + return ctx.ack(":wave: Hello!"); + }); + + // SocketModeApp expects an env variable: SLACK_APP_TOKEN + new SocketModeApp(app).start(); + } +} +``` + +If you go with JDK 10+, thanks to [Local Variable Type Inference](https://developer.oracle.com/java/jdk-10-local-variable-type-inference.html), your code could be much more concise. To take advantage of it, install OpenJDK 11 and set the compatible Java versions in `build.gradle` as below. Also, configure the same on your IDE. + +```groovy +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} +``` + +Now, you don't need to repeat the same type in a single line. + +```java +var app = new App(); +app.command("/hello", (req, ctx) -> { + return ctx.ack(":wave: Hello!"); +}); +new SocketModeApp(app).start(); +``` + + + + Only single source code is required to run your first-ever Bolt app. All you need to do is define the main method that starts `SlackAppServer`. Your server with the default configuration will listen to the 3000 port but it's configurable. Check other constructors of the class to customize the behavior. ```java @@ -148,7 +322,10 @@ var server = new SlackAppServer(app); server.start(); ``` -### Start the App with Two Env Variables + + + +### Environment variables {#env-variables} The default constructor expects the following two env variables exist when starting the app. @@ -180,20 +357,53 @@ mvn compile exec:java -Dexec.mainClass="hello.MyApp" You will see the message saying "**⚡️ Bolt app is running!**" in stdout. -If you get stuck this setup, go through the following checklist: +If you get stuck, go through the following checklist: -- [X] JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) -- [X] Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) -- [X] `build.gradle` has `bolt-jetty` dependency and valid application plugin settings -- [X] `src/main/java/hello/MyApp.java` with a class having its main method -- [X] [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`app_mentions:read`](https://api.slack.com/scopes/app_mentions:read) bot scope, install the app to your development workspace -- [X] Copy [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**Signing Secret**](https://api.slack.com/docs/verifying-requests-from-slack) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables + + -### Enable `/hello` Command +* ✅ JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) +* ✅ Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) +* ✅ `build.gradle` has `bolt-socket-mode` and `tyrus-standalone-client` in the dependencies and valid application plugin settings +* ✅ `src/main/java/hello/MyApp.java` with a class having its main method +* ✅ [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`commands`](https://api.slack.com/scopes/commands) bot scope, add **an app-level token with `connections:write` scope**, and install the app to your development workspace +* ✅ Copy [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**App-Level Token**](https://api.slack.com/docs/token-types#app) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables + + + + +* ✅ JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) +* ✅ Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) +* ✅ `build.gradle` has `bolt-jetty` dependency and valid application plugin settings +* ✅ `src/main/java/hello/MyApp.java` with a class having its main method +* ✅ [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`app_mentions:read`](https://api.slack.com/scopes/app_mentions:read) bot scope, install the app to your development workspace +* ✅ Copy [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**Signing Secret**](https://api.slack.com/docs/verifying-requests-from-slack) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables + + + + +### Enabling the `/hello` Command {#hello} Your app is up now! However, the slash command `/hello` in the code is still unavailable. To enable it, follow the steps below: -* Set up some way to allow Slack API server to access your Bolt app + + + +* Visit [Slack App configuration pages](https://api.slack.com/apps) +* Choose your app +* Go to **Settings** > **Socket Mode** on the left pane + * Turn on **Enable Socket Mode** +* Go to **Features** > **Slash Commands** on the left pane + * Click **Create New Command** button + * Input the command information on the dialog: + * **Command**: `/hello` + * **Short Description**: whatever you like + * Click **Save** Button + + + + +* Configure a way to allow Slack API server to access your Bolt app * A well-known way is to use [ngrok](https://ngrok.com/) - install it and run `ngrok http 3000` on another terminal * Configure & Reinstall the Slack App * Visit [Slack App configuration pages](https://api.slack.com/apps) @@ -206,9 +416,12 @@ Your app is up now! However, the slash command `/hello` in the code is still una * Click **Save** Button * Go to **Settings** > **Install App** and click **Reinstall App** button + + + Now you can hit the `/hello` command in your development workspace. If your app is successfully running, the app should respond to the command by replying `👋 Hello!`. -### OK, What about Spring Boot? +### What about Spring Boot? {#spring-boot} As [Spring Boot](https://spring.io/projects/spring-boot) is one of the most popular web frameworks in the Java world, you may be curious about the possibility to let this Bolt live together with it. @@ -238,11 +451,40 @@ public class SlackAppController extends SlackAppServlet { Check [the detailed guide here](/guides/supported-web-frameworks) for further information. --- -## Getting Started in Kotlin {#getting-started-in-kotlin} +## Getting started with Kotlin {#getting-started-in-kotlin} For code simplicity, [Kotlin](https://kotlinlang.org/) language would be a great option for writing Bolt apps. In this section, you'll learn how to set up a Kotlin project for Bolt apps. -#### `build.gradle` +**Using `build.gradle`** + + + + +Most of the build settings are necessary for enabling Kotlin language. Adding `bolt-socket-mode` && `tyrus-standalone-client` to the dependencies is the only one that is specific to Bolt. + +```groovy +plugins { + id("org.jetbrains.kotlin.jvm") version "kotlinVersion" + id("application") +} +repositories { + mavenCentral() +} +dependencies { + implementation(platform("org.jetbrains.kotlin:kotlin-bom")) + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("com.slack.api:bolt-socket-mode:sdkLatestVersion") + implementation("javax.websocket:javax.websocket-api:javaxWebsocketApiVersion") + implementation("org.glassfish.tyrus.bundles:tyrus-standalone-client:tyrusStandaloneClientVersion") + implementation("org.slf4j:slf4j-simple:slf4jApiVersion") // or logback-classic +} +application { + mainClassName = "MyAppKt" // add "Kt" suffix for main function source file +} +``` + + + Most of the build settings are necessary for enabling Kotlin language. Adding `bolt-jetty` dependency is the only one that is specific to Bolt. @@ -265,12 +507,35 @@ application { } ``` + + + If you're already familiar with Kotlin and prefer the Gradle Kotlin DSL, of course, there is nothing stopping you. -#### `src/main/kotlin/MyApp.kt` + +**Using `src/main/kotlin/MyApp.kt`** Here is a minimum source file that just starts a Bolt app on your local machine. + + + +```kotlin +import com.slack.api.bolt.App +import com.slack.api.bolt.socket_mode.SocketModeApp + +fun main() { + val app = App() + + // Write some code here + + SocketModeApp(app).start() +} +``` + + + + ```kotlin import com.slack.api.bolt.App import com.slack.api.bolt.jetty.SlackAppServer @@ -285,18 +550,12 @@ fun main() { } ``` -### Make Sure If It Works - -OK, you should be done. Just in case, here is the checklist: + + -- [X] JDK 8 or higher installed (if not, run `brew install openjdk@11` for macOS / visit [OpenJDK website](https://openjdk.java.net/install/) for others) -- [X] Gradle installed (if not, run `brew install gradle` for macOS / visit [their website](https://gradle.org/) for others) -- [X] `build.gradle` with valid Kotlin language settings and `bolt-jetty` dependency -- [X] `src/main/kotlin/MyApp.kt` with a main method -- [X] [Create a Slack App](https://api.slack.com/apps?new_app=1), add [`app_mentions:read`](https://api.slack.com/scopes/app_mentions:read) bot scope, install the app to your development workspace -- [X] Copy the [**Bot User OAuth Access Token**](https://api.slack.com/docs/token-types#bot) and [**Signing Secret**](https://api.slack.com/docs/verifying-requests-from-slack) from [your Slack App admin pages](https://api.slack.com/apps) and set them to env variables +### Running your Kotlin app {#run-kotlin} -If all are ✅, bootstrapping your first-ever Kotlin-flavored Bolt app will succeed. +If all items from the checklist are ✅, bootstrapping your first-ever Kotlin-flavored Bolt app will succeed: ```bash # Visit https://api.slack.com/apps to know these @@ -307,10 +566,6 @@ export SLACK_SIGNING_SECRET=123abc...your-own-valid-one gradle run ``` -... Did you see the message saying "**⚡️ Bolt app is running!**" in `stdout`? - -If yes, that's all settled! 🎉 - From here, all you need to do is write code and restart the app. Enjoy Bolt app development in Kotlin! 👋 :::tip @@ -320,7 +575,7 @@ We strongly recommend using [IntelliJ IDEA](https://www.jetbrains.com/idea/) her ::: --- -## Next Steps +## Next steps {#next-steps} Read the [Bolt Basics](/guides/bolt-basics) page for further information. diff --git a/docs/content/index.md b/docs/content/index.md index 91eff6758..1aef8c6f4 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -3,10 +3,10 @@ The Java Slack SDK supports the Slack platform in a Java idiomatic way. Developers can use it in any JVM language including Kotlin, Groovy, and Scala. -Within the SDK, there are two different modules: +Within these docs, there are two different modules: -* [Bolt for Java](/guides/getting-started-with-bolt), which is a framework with a simple API that makes it easy to write modern Slack apps in Java. -* [Slack API Client](/guides/web-api-basics), for when you need a more customized approach to building a Slack app in Java. +* [Bolt for Java Guides](/guides/getting-started-with-bolt), which is a framework with a simple API that makes it easy to write modern Slack apps in Java. +* [Java SDK Guides](/guides/web-api-basics), for when you need a more customized approach to building a Slack app in Java using the Slack API client. ## Requirements @@ -16,9 +16,9 @@ Users can expect every single patch release has been done after verifying functi ## Getting help -These docs have lots of information on the Java Slack SDK. There's also an in-depth Reference section. Please explore! +These docs have lots of information on Bolt for Java and the Java Slack SDK. There's also an in-depth Reference section. Please explore! -If you otherwise get stuck, we're here to help. The following are the best ways to get assistance working through your issue: +If you get stuck, we're here to help. The following are the best ways to get assistance working through your issue: * Visit the [Issue Tracker](http://github.com/slackapi/java-slack-sdk/issues) for questions, bug reports, feature requests, and general discussion related to Bolt for JavaScript. Try searching for an existing issue before creating a new one. * Visit the [Slack Developer Community](https://slackcommunity.com/) for getting help or for just bonding with your fellow Slack developers. diff --git a/docs/sidebars.js b/docs/sidebars.js index 8434bd652..d248cd142 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -20,70 +20,52 @@ const sidebars = { label: 'Java Slack SDK', className: 'sidebar-title', }, - { type: 'html', value: '
' }, + {type: 'html', value: '
'}, { type: 'category', - label: 'Guides', + label: 'Bolt for Java Guides', items: [ - { - type: 'category', - label: 'Getting Started', - items: [ - 'guides/getting-started-with-bolt', - 'guides/bolt-basics', - 'guides/supported-web-frameworks', - ], - }, - { - type: 'category', - label: 'Slack API calls', - items: ['guides/composing-messages', 'guides/web-api-basics', 'guides/web-api-client-setup'], - }, + 'guides/getting-started-with-bolt', + 'guides/bolt-basics', + 'guides/supported-web-frameworks', + 'guides/socket-mode', 'guides/events-api', { - type: 'category', - label: 'App UI & Interactivity', - items: [ - 'guides/interactive-components', - 'guides/shortcuts', - 'guides/modals', - ], - }, + type: "category", + label: "App UI & Interactivity", + items: ['guides/interactive-components', 'guides/modals', 'guides/app-home',], + }, 'guides/assistants', + 'guides/shortcuts', + 'guides/slash-commands', { - type: 'category', - label: 'App Configuration', - items: [ - 'guides/app-home', - 'guides/socket-mode', - 'guides/slash-commands', - 'guides/incoming-webhooks', - ], - }, + type: "category", + label: "Authorization & Security", + items: ['guides/app-distribution', 'guides/sign-in-with-slack',], + }, { - type: 'category', - label: 'Authorization & Security', - items: ['guides/app-distribution', 'guides/sign-in-with-slack'], - }, + type: "category", + label: "Admin Tools", + items: ['guides/web-api-for-admins', 'guides/scim-api', 'guides/audit-logs-api', 'guides/status-api'], + }, { - type: 'category', - label: 'Admin Tools', - items: ['guides/web-api-for-admins', 'guides/scim-api', 'guides/audit-logs-api', 'guides/status-api'], - }, - { - type: 'category', - label: 'Legacy', - items: ['guides/steps-from-apps', 'guides/rtm'], - }, + type: "category", + label: "Legacy", + items: ['guides/steps-from-apps',], + }, ], }, {type: 'html', value: '
'}, { type: 'category', - label: 'Tutorials', + label: 'Java Slack SDK Guides', items: [ - 'guides/getting-started-with-bolt-socket-mode', - ], + 'guides/web-api-basics', + 'guides/web-api-client-setup', + 'guides/composing-messages', + 'guides/incoming-webhooks', + 'guides/rtm', + ], }, {type: 'html', value: '
'}, 'reference', From 4b58ecbff96b8f1065a564ffdbfec3dc2306ece9 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Fri, 7 Feb 2025 11:00:53 +0900 Subject: [PATCH 3/3] Apply suggestions from code review --- docs/content/guides/assistants.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/guides/assistants.md b/docs/content/guides/assistants.md index 0c83ed79d..29c14ef67 100644 --- a/docs/content/guides/assistants.md +++ b/docs/content/guides/assistants.md @@ -84,7 +84,7 @@ Be sure to give the [assistants reference docs](/reference#agents--assistants) a When the user opens a new thread with your assistant, the [`assistant_thread_started`](https://api.slack.com/events/assistant_thread_started) event will be sent to your app. :::tip -When a user opens an assistant thread while in a channel, the channel info is stored as the thread's `AssistantThreadContext` data. You can grab that info by using the `get_thread_context` utility, as subsequent user message event payloads won't include the channel info. +When a user opens an assistant thread while in a channel, the channel info is stored as the thread's `AssistantThreadContext` data. You can grab that info by using the `context.getThreadContext()` utility, as subsequent user message event payloads won't include the channel info. ::: ### Block Kit interactions in the assistant thread {#block-kit-interactions} @@ -181,7 +181,7 @@ If you use the built-in `Assistant` middleware without any custom configuration, As long as you use the built-in approach, you don't need to store the context data within a datastore. The downside of this default behavior is the overhead of additional calls to the Slack API. These calls include those to `conversations.history`, which are used to look up the stored message metadata that contains the thread context (via `context.getThreadContextService().findCurrentContext(channelId, threadTs)`). -If you prefer storing this data elsewhere, you can pass your own custom `AssistantThreadContextStore` implementation to the `Assistant` constructor. We provide `FileAssistantThreadContextStore`, which is a reference implementation that uses the local file system. Since this reference implementation relies on local files, it's not advised for use in production. For production apps, we recommend creating a class that inherits `AssistantThreadContextStore`. +If you prefer storing this data elsewhere, you can pass your own custom `AssistantThreadContextService` implementation to the `Assistant` constructor. We provide `DefaultAssistantThreadContextService`, which is a reference implementation that uses the assistant thread message metadata. You can use this for production apps, but if you want to use a different datastore for it, you can implement your own class that inherits `AssistantThreadContextService` interface. ```java Assistant assistant = new Assistant(new YourOwnAssistantThreadContextService());