A chatbot (or chatterbot, as Wikipedia says) is a piece of software that talks to you in chat format. We use chatbots in a few (micro)services, and they fully replace user interfaces. I don't think there is any innovation in this approach, but it has proved to be very effective over the last year or so. That's the impetus for this post. Here is how the Rultor chatbot works for us and what its benefits are.
Let me give an example first. Look at the jcabi/jcabi-http#115 GitHub ticket:
Let's see what's going on here, and then we'll discuss how it's designed inside. Essentially, I'm talking to a chatbot here. The name of the chatbot is
@rultor (I wrote about it last year). At 1, I'm asking the chatbot to release a new version of the jcabi-http library. At 2, the chatbot responds, just confirming that the task is clear and that it's on it. At 3, the bot says the job is completed and its completion took nine minutes. Our conversation is over. That's it.
Now, what is so special about this?
One thing: There is no user interface. Well, there is no traditional web-based HTML/CSS user interface. There is no login, logout, profile, menu, or anything like this. Rultor is a web service that has no web UI. The only way to communicate with it is by talking with its chatbot.
What's so good about it? A few things.
Service Is Not a Server
This is how the traditional architecture of a web system would look:
A user gives instructions to a service and receives responses. This communication happens through a user interface (UI)—a bunch of HTTP entry points that receive requests from a browser and return HTML+CSS responses. Or, if a user is on another service, requests may contain some data, and responses will be in XML or JSON. You get the idea; a user is a client, and the service is a server.
Like in a restaurant—you say what you want, and a server goes to the kitchen, waits there, and in a few minutes, comes back with spaghetti carbonara. You're a client, and that cute lady is a server.
In the case of a chatbot, that's not the case anymore. Look at the architecture:
First, a user posts a request to GitHub through a web user interface provided by GitHub. It is a communication hub for us. Then, the service connects to GitHub through its RESTful API and checks whether there are any new requests there. If something new is found, the service does the job, prepares a response, and posts it there. The client receives an email notification about a new response just posted to the ticket. The client then checks GitHub and finds the response.
Here is how this would look in a restaurant: There would be a board with sticky notes. First, you write the note, "I'd like spaghetti carbonara with parmesan and fresh pepper on top" (Damn, I'm just too hungry now), and pin it to the board at number 15. Then, you return to your table. A chef from the kitchen checks that board and finds your sticky note. He makes that spaghetti, tops it with parmesan, fresh pepper, some basil leaves, and virgin olive oil ... yeah, he makes it right ... and puts it next to the board. You hear an announcement that order number 15 is ready. You go there, collect the food, return to your table, and enjoy.
The point is that there is no cute lady involved anymore. There is no server. There are two parties communicating with the board—you and the kitchen. The kitchen is our microservice, but it's not a server anymore.
These two parties are perfectly decoupled now. They never talk to each other. And they both are clients of the communication hub, which is GitHub or a board in the restaurant.
Again, the microservice is not a server anymore. Instead, it is a client of a communication hub. And the flip of its position provides a lot of benefits to us, its developers.
No Need to Be Fast
First of all, we don't need to care much about the performance of our UI. Well, we don't care at all, since we don't have a UI. Do we care about the speed of responses on GitHub? Not really. When a user posts a message to GitHub, he or she doesn't expect our chatbot to give an immediate answer in less than 100 milliseconds. (That's what any properly designed web system must guarantee, I believe.)
We put a note on the board, and we assume that the kitchen is probably doing something else at the moment. We'll wait for a few seconds or even minutes. If, on the other hand, I give an order to the waitress and she waits five seconds before replying back, I'll be very surprised. If she keeps doing that with every question, I'll start to wonder to myself if everything is OK with her.
I expect a user interface to be instant, while in a chat I have no problem allowing some time for the bot to answer. This happens naturally. We're used to delays in chats, when we're talking with real people. They need some time to process our information, to think, and to type something back.
But a user interface doesn't have that luxury. It has to be bullet-fast; otherwise, I immediately get frustrated. The same thing happens to you, right?
No Need to Look Cute
Another advantage of this no-server design is that there is no need to look pretty. There is no web interface, no HTML, no CSS, no graphic design. Perhaps not everybody really likes that. Most non-professional users may still prefer to talk to a cute server instead of sticking some paper notes to the board. But if we're dealing with professional computer engineers, they're not that demanding.
Rultor doesn't have any web UI, and its users simply don't know how it "looks." It just talks to you. The only thing you see is its avatar in GitHub.
This saves a lot of money and time on design efforts, which are usually very expensive if you aim for high quality. If your web service looks average, most of its users will assume that it also works average. Many good ideas have simply died because their UI wasn't as impressive as people were used to, thanks to all those Pinterests and Instagrams.
A good-looking server has a greater chance for bigger tips, right? If there is no server and we don't see the chef, we judge him or her only by the quality of the food.
Same here. By getting rid of a UI, we allow ourselves to focus on the quality of the service we're delivering. We don't burn our time and money on being nice. We spend them on being useful.
Much Easier to Scale
If we have too many stickies on that board, we just hire more cooks, or maybe even build another kitchen, and the problem is solved. We can handle as many customers as necessary. Well, as long as the board is powerful enough to handle multiple parallel users.
GitHub is a pretty big platform, with hundreds of thousands of users and projects. If we have too many requests coming in, we can just add more processing nodes to Rultor. Remember, we're not a server anymore; we are a client of GitHub. We decide when to connect to GitHub and when to create responses to the requests submitted.
It is much easier to create a scalable client than a scalable server, mostly because there is nobody really waiting for us to respond quickly. The load of requests we're getting can be managed much easier, since the decision of when to process them is made by us.
Mistakes Are Not So Visible
When you're standing in front of a customer, most of your mistakes are unforgivable, primarily because they are very visible. On the other hand, when you're cooking something in the kitchen, nobody can see you and spot your faults. They will only spot them if the spaghetti has too much salt. In other words, they will judge you by your results, not by how you produce them.
It's the same story with the microservice. When it works as a server, we expect it to be seamless, respond immediately, and present everything in a structured and organized way. If something goes wrong, it's right here on the web page. Your best case is a 404, while the worst one is that you present some wrong information to the user. Even though the bug may not be critical inside the microservice engine, the user doesn't know that. The user will judge you by your appearance and won't forget even small mistakes.
However, when you both are clients of a message board, you don't see each other. The user communicates with GitHub, and the microservice interacts with GitHub. Mistakes are less visible. Trust me, we have had many of them over the 18 months that Rultor has been in public use. We've had downtimes, we've had serious logical mistakes, and we've had data corruption. But very rarely have these problems become visible online. We merely saw them in our server logs. Users didn't see them. Well, mostly :)
Everything Is Traceable
Since there is a communication board between us, it's very easy to see the entire history of our discussion, which is very intuitive. It's like a Slack chat history. You see what we started from, who said what, and which conclusions were made.
Basically, you can't have that visibility in a web UI. Well, you can probably create a special page with the "history of operations," but who would check it? And how visible and simple would that information be? And, what's most important, how would that information match up with the UI?
In the log, you'll state that "the build was started," but what's the build and how was it started? How can I start it again? Using which buttons and web controls? It's not clear.
Thus, the traceability of a chronological chat is unbeatable.
Easy to Integrate With Other Services
Yes, think about the future of this approach. If there is a centralized message board where users talk to a chatbot, why can't other chatbots talk to each other too?
Forget about RESTful APIs. Just a message board where chatbots post their requests and collect responses. They are perfectly decoupled, replaceable, and very scalable. Also, their communication protocol is visible and very traceable. And they boast many other benefits, as was just explained above. It's much more convenient for us, both users and programmers, to monitor them and create them.
Well, maybe it's too extreme to get rid of RESTful APIs entirely, but to some extent, this approach is feasible, I believe.
I didn't go too far with this idea, but something was done. We have a messaging platform that allows multiple chatbots to communicate with users. It's called Netbout. It's a very primitive web system with isolated discussions. Simply put, anyone can create a new discussion, invite a few friends, and post messages there. Both users and chatbots can do that.
So, when a new candidate wants to join Teamed.io, we ask that person to fill out an online form. When the candidate clicks the "Submit" button, a new discussion starts, and the first chatbot decides who should interview that person. The decision is made according to the skills listed in the form. The chatbot invites one of our best programmers to conduct the interview. When the interview is done, another chatbot explains to the candidate what the next steps are, registers him or her in our database, and starts to show the progress of work.
From a user perspective, it looks like he or she is talking to a few people who understand just a few simple commands. It is very intuitive and was easy to design.
I think chatbots are a good approach for interacting with microservices. Especially when users are more or less professional.
PS. Illustrations by Kristina Wheat.