The Einstein Bots Platform API is a new REST API that allows you to interact with your Einstein Bots from any client. We’ve also created an open-source Java SDK and Channel Connector to give you the tools you need to easily integrate Einstein Bots into any of your conversational channels on top of the existing digital engagement channels that are supported by Service Cloud.

In the previous post, we showed how to use a basic bot client with the Java SDK to connect your channel to the Einstein Bot. In this post, we will look at the SDK’s session-managed client and its features. You’ll learn how to simplify your implementation by automatically managing sessions for your conversation channel. Additionally, you’ll learn to how to use the included cache, or provide a custom cache implementation, with the session-managed client.

Recap of the basic bot client

Before looking at a session-managed client, let’s do a quick recap. Here are the high-level steps to using the basic bot client. You can find code examples in our previous post.

  1. Create a basic chatbot client
  2. Call the startChatSession() method to start a session using your ExternalSessionId
  3. Retrieve RuntimeSessionId from the bot’s response
  4. Call the sendMessage() method using RuntimeSessionId to send a message to the active session
  5. Call the endChatSession() method to end the session when the conversation ends

Here’s the BasicChatbotClient interface for your reference.

public interface BasicChatbotClient {

  BotResponse startChatSession(RequestConfig config,
                               ExternalSessionId sessionId,
                               BotSendMessageRequest requestEnvelope);
  
  BotResponse sendMessage(RequestConfig config,
                          RuntimeSessionId sessionId,
                          BotSendMessageRequest requestEnvelope);

  BotResponse endChatSession(RequestConfig config,
                             RuntimeSessionId sessionId,
                             BotEndSessionRequest requestEnvelope);
}

When should a new session start?

The challenge is that you must know when you have to start a new session (versus send a message to an existing session) and call methods startChatSession() and sendMessage() appropriately. In some cases, the channel doesn’t have clear boundaries between sessions to be able to tell when a new conversation session begins.

For example, let’s say a bot is listening on a Slack channel and a user posts a message. You must start a new session when the user posts a message for the first time (or after a long time, based on session time-out). Alternatively, if the user is already in active conversation, you can just send a message to the existing session.

To send a message to the existing session, you have to track the active sessions of users along with RuntimeSessionId. The good news is that the session-managed client already provides this functionality, so you don’t have to implement it.

Introducing the session-managed client

Let’s first look at the SessionManagedChatbotClient interface to see the difference between it and the BasicChatbotClient noted above.

// The session-managed bot client
public interface SessionManagedChatbotClient {

  BotResponse sendMessage(RequestConfig config,
                          ExternalSessionId sessionId,
                          BotSendMessageRequest requestEnvelope);
                        
  BotResponse endChatSession(RequestConfig config,
                             ExternalSessionId sessionId,
                             BotEndSessionRequest requestEnvelope);
}

Notice two differences from the BasicChatbotClient interface:

  • There’s no startChatSession method, but only sendMessage
  • The methods accept only ExternalSessionId as parameter

The benefit of using a session-managed client is that you don’t have to call the startChatSession() method explicitly, and you don’t have to know about RuntimeSessionId. The session-managed client will take care of the entire session management for you, and your application code can remain stateless. All the heavy lifting of maintaining the mapping between ExternalSessionId and RuntimeSessionId, along with determining when to start a new session, is taken care of by the session-managed client.

Using a session-managed client

Enough theory — let’s write some code for using a session-managed client. In this section, you’ll learn how to implement a full conversation life cycle, such as initiating a chat session, sending a message to the current session, and ending a chat session.

1. Add a POM dependency

Find the latest einstein-bot-sdk-java version from Maven Central and add this dependency to your pom.xml .

<dependency>
  <groupId>com.salesforce.einsteinbot</groupId>
  <artifactId>einstein-bot-sdk-java</artifactId>
  <version>${einstein-bot-sdk-java-version}</version>
</dependency>

2. Create a session-managed client

The SessionManagedChatbotClient uses JwtBearerFlow for OAuth, and it adds session management capabilities on top of the BasicChatbotClient. The next step is to pass AuthMechanism and BasicChatbotClient as parameters for SessionManagedChatbotClient.

// Create a JWT Bearer authentication mechanism.
AuthMechanism oAuth = JwtBearerOAuth.with()
    .privateKeyFilePath(privateKeyFilePath)
    .loginEndpoint(loginEndpoint)
    .connectedAppId(connectedAppId)
    .connectedAppSecret(secret)
    .userId(userId)
    .build();

// Create a session-managed client.
SessionManagedChatbotClient client = ChatbotClients
    .sessionManaged()
    .basicClient(ChatbotClients.basic()
        .basePath(basePath)
        .authMechanism(oAuth)
        .build())
    .cache(new RedisCache(YOUR_TTL_SECONDS,YOUR_REDIS_URL))
    .build();

We’ll discuss the cache parameter later in this post.

3. Create a request config

Create a RequestConfig with your botId, orgId, and forceConfigEndPoint. To find these values, refer to the Einstein Bots API Developer Guide. Typically, you want to create a config one time per bot in your org and reuse it for every request.

//Create Request Config
RequestConfig config = RequestConfig.with()
    .botId(botId)
    .orgId(orgId)
    .forceConfigEndpoint(forceConfigEndPoint)
    .build();

4. Send a message

First, create an ExternalSessionId to uniquely identify a session in your channel. For example, it could be “userId” for Slack, or “twitter thread” for Twitter. Then, create a BotSendMessageRequest and call the sendMessage method to send.

// Retrieve the external session ID from the external channel.
// For example, it could be userId for slack, twitter thread for twitter. 
// For this example, we use random UUID 
ExternalSessionId externalSessionId = 
    new ExternalSessionId(UUID.randomUUID().toString());

// Build the request to send a message to the bot.
BotSendMessageRequest sendMessageRequest = BotRequest
    .withMessage(buildTextMessage(message))
    .build();

// Send the request using the external session ID.
BotResponse response = client
   .sendMessage(config, externalSessionId, sendMessageRequest);

The BotResponse object is the same as with the BasicChatbotClient, so you can retrieve the bot’s response in the same way as described in the previous blog post.

5. End the bot session

The code is the same as with the BasicChatbotClient except that you pass an ExternalSessionId instead of the bot’s internal session ID.

// Build the request to end the bot session.
BotEndSessionRequest botEndSessionRequest = BotRequest
    .withEndSession(EndSessionReason.USERREQUEST).build();

// Send the request to the bot to end the session.
BotResponse endSessionResponse = client
    .endChatSession(config, externalSessionId, botEndSessionRequest);

How the session-managed client tracks sessions

You’ve now learned to use the session-managed client provided by the SDK, but session tracking logic will depend on your channel, and you might need to customize it for your use case. So, it’s useful to understand how the session-managed client works.

The session-managed client tracks sessions based on a combination of ExternalSessionId, BotId, and OrgId. If the client sends a message request with a new combination of those IDs, it automatically calls startChatSession to start the chat session. It retrieves the RuntimeSessionId from startChatSession and adds mapping between active sessions and RuntimeSessionId in a Cache. If the combination of ExternalSessionId, BotId, and OrgId already exists in Cache, it will sendMessage to the existing session using the cached RuntimeSessionId value.

The Cache can now be customized for your needs.

Customizing the cache used by the session-managed client

You are almost done! In this last section, you will learn how to customize the cache for your needs because the cache
is an important layer that is specific to your application architecture.

Choosing a cache library

We have included InMemoryCache and RedisCache out of the box. InMemoryCache helps you easily run in a development environment. It isn’t recommended for use in a production org.

You can use RedisCache to easily deploy and run it in a cloud infrastructure. If you can’t use Redis, you can provide your own cache implementation.

Providing your own cache implementation

If you want to use any other distributed cache service (for example, Memcached), we’ve provided a cache abstraction. You can implement this cache interface according to your cache system and pass it to .cache method of the session-managed client builder.

Summary

To recap, you have learned how to simplify your Einstein Bots integration using the session-managed client and how to customize it for your needs. This saves you time because:

  • The session-managed client simplifies connecting to Einstein Bots by automatically managing sessions
  • You don’t need to explicitly start a session or track runtime session IDs
  • You can use the provided RedisCache or provide your own cache implementation for tracking sessions

To learn more, refer to Einstein Bot SDK user guide.

About the author

Rajasekar Elango is a Principal Software Engineer at Salesforce working on the Einstein Bots Platform. You can follow him on LinkedIn or Twitter.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS