Chatto is a minimal chatbot framework in Go.


Documentation codecov Go Report Card GoDoc Docker Image Version (latest by date)



Simple chatbot framework written in Go, with configurations in YAML. The aim of this project is to create very simple text-based chatbots using a few configuration files.

The inspiration for this project originally came from Flottbot and my experience using Rasa.




go get -u

Via Docker:

docker pull jaimeteb/chatto:latest


See the Documentation for examples, configuration guides and reference.


Your first bot

Chatto combines the consistency of a finite-state-machine with the flexibility of machine learning. It has three main components: the classifier, the finite-state-machine and the extensions.

A very basic directory structure for Chatto would be the following:

   ├── clf.yml
   └── fsm.yml

Start by creating the data directory as well as the YAML files.

mkdir data
touch data/clf.yml data/fsm.yml

The clf.yml file

The clf.yml file defines how the user messages will be classified into commands (intents). Start with this very simple configuration:

  - command: "turn_on"
      - "turn on"
      - "on"

  - command: "turn_off"
      - "turn off"
      - "off"

The fsm.yml file

The fsm.yml file defines the transitions between states, the commands that make these transitions, and the answers to be sent in them. Start with this file contents:

  - from:
      - "initial"
    into: "on"
    command: "turn_on"
      - text: "Turning on."

  - from:
      - "on"
    into: "initial"
    command: "turn_off"
      - text: "Turning off."
      - text: ""

  unknown: "Can't do that."

Run your first bot

To start your bot, run:

chatto --path data/

If you're using Docker, run:

docker run \
    -it \
    -e CHATTO_DATA=./data \
    -v $PWD/data:/data \
    jaimeteb/chatto:latest \
    chatto --path data

Interact with your first bot

To interact with your bot, run:

chatto cli

That's it! Now you can say turn on or on to go into the on state, and turn off or off to go back into initial. However, you cannot go from on into on, or from initial into initial either.

Here is a diagram for this simple Finite State Machine:

ON/OFF Finite State Machine


You can integrate your bot with Telegram, Twilio, Slack and anything you like

Run chatto in the directory where your YAML files are located, or specify a path to them with the --path flag:

chatto --path ./your/data

To run on Docker, use:

docker run \
  -p 4770:4770 \
  -e CHATTO_DATA=./your/data \
  -v $PWD/your/data:/data \


You can use the Chatto CLI tool by downloading the chatto cli tool. The CLI makes it easy to test your bot interactions.

chatto cli --url '' -port 4770

Docker Compose

You can use Chatto on Docker Compose as well. A docker-compose.yml would look like this:

version: "3"

    image: jaimeteb/chatto:${CHATTO_VERSION}
    env_file: .env
      - "4770:4770"
      - ${CHATTO_DATA}:/data
      - ext
      - redis

    image: odise/busybox-curl # Busy box with certificates
    command: ext/ext
      - 8770
      - ${CHATTO_DATA}/ext:/ext

    image: bitnami/redis:6.0
      - 6379

This requires a .env file to contain the necessary environment variables:

# Chatto configuration

# Extension configuration

# Redis

# Logs

The directory structure with all the files would look like this:

├── data
│   ├── ext
│   │   ├── ext
│   │   └── ext.go
│   ├── bot.yml
│   ├── chn.yml
│   ├── clf.yml
|   └── fsm.yml
├── docker-compose.yml
└── .env

Finally, run:

docker-compose up -d redis ext
docker-compose up -d chatto

The extensions server has to be executed according to its language.

For this docker-compose.yml file, you'd have to build the Go extension first:

go build -o data/ext/ext data/ext/ext.go

The extensions server has to be running before Chatto initializes.


Under the deploy/kubernetes directory you can find an example deployment:

Kind Name Description
Secret chatto-config-secrets Contains the tokens that Chatto will use for authorization
ConfigMap chatto-config-envs Contains the environment variables for the bot.yml file
ConfigMap chatto-config-files Contains the clf.yml and fsm.yml file
Deployment chatto Chatto deployment based on the jaimeteb/chatto Docker image
Service chatto-service Service for the chatto deployment
Ingress chatto-ingress Ingress for the chatto-service service

Run the following command to deploy on Kubernetes:

kubectl apply -f ./deploy/kubernetes/


An importable bot server and client package is provided to allow embedding into your own application.

To embed the server:

package main

import (


func main() {
	port := flag.Int("port", 4770, "Specify port to use.")
	path := flag.String("path", ".", "Path to YAML files.")

	server := bot.NewServer(*path, *port)


To embed the client:

package myservice

import (


type MyService struct {
	chatto bot.Client

func NewMyService(url string, port int) *MyService {
	return &MyService{chatto: bot.NewClient(url, port)}

func (s *MyService) Submit(question *query.Question) error {
	answers, err := s.chatto.Submit(question)
	if err != nil {
		return err

	// Print answers to stdout
	for _, answer := range answers {

	return nil


I have provided some config files under examples. Clone the repository and run chatto with the -path of your desired example to test them out (for the ones that use extensions, run their respective extensions first).

More about these examples in the Documentation

  1. Mood Bot - A chatto version of Rasa's Mood Bot Greet the bot to start the conversation.
  2. Pokemon Search - Search for Pokémon by name or number.
  3. Miscellaneous Bot - Weather forecast, random jokes and quotes, and more!
  4. Trivia Quiz - Type start to take a quick trivia quiz.
  • initial support of slack socket mode - refactor

    initial support of slack socket mode - refactor

    I played around with the Slack integration what I was looking for is to use socket mode so we don't have to expose this chat bot to the internet. Here is my WIP.

    opened by ryancurrah 30
  • Add token authorization option for extensions

    Add token authorization option for extensions

    Addresses #11

    Tests pending.

    The token will only be supported by REST extensions.

    @ryancurrah what do you think?

    opened by jaimeteb 15
  • refactor: use internal directory for private apis

    refactor: use internal directory for private apis

    Use internal dir for private APIs while improving the public APIs for consumption. Also adding more tests.

    opened by ryancurrah 10
  • feat: k8s example deployment with some goodies

    feat: k8s example deployment with some goodies

    If the FSM and CLF configs change chatto will auto-reload them. Set consistent env var names. Added an example deployment. Allow setting debug through env var.


    opened by ryancurrah 7
  • Add new channel for Slack

    Add new channel for Slack

    Awesome project. What would it take add a new slack integration?

    opened by ryancurrah 6
  • feat: allow using multiple extension servers

    feat: allow using multiple extension servers

    This feature allows using multiple extension servers. If connecting to an extension fails, an error will be logged instead of killing the Chatto server. That way, if an extension is not running, Chatto can still operate.

    It is key to note that in this solution, we cannot have duplicate extension names. If two extension servers provide the same extension name Chatto will error out on startup. This could cause a denial of service. I am going to think 🤔 this one through, not sure I like it causing Chatto to fatally error out.


    • EDIT (Monday, March, 8th - 9:35AM EST)

    One thought I had was to require extensions to have a namespace associated to them. This would allow duplicate extension commands without naming collisions. As each command would be in it's own extension namespace.


        type: RPC
        port: 9001
        type: REST
        port: 8080

    fsm.yml config option 1 with a dot notation of <extension_name>.<extension_command>

       - from:
          - search_pokemon
         into: initial
         command: any
           name: pokemon
           mode: whole_text
         extension: pokemon.search_pokemon


    fsm.yml config option 2 with a dictionary of name and command

      - from:
          - search_pokemon
        into: initial
        command: any
          name: pokemon
          mode: whole_text
          name: pokemon
          command: search_pokemon

    I kind of prefer the later, option 2. The reason for that is, is if we need to expand the extension options for the fsm later it would not be a breaking change.

    opened by ryancurrah 6
  • more complicated example?

    more complicated example?

    A more complicated example, for instance, we want a robot that can solve some basic functions like what's the weather today? Tell me a joke, do u know how is the tallest man in the world, how to combines all these intent into a full example?

    opened by jinfagang 5
  • feat: add the concept of conversations

    feat: add the concept of conversations

    Addresses Still need to add tests.

    opened by ryancurrah 5
  • feat: detect commands and states from transitions

    feat: detect commands and states from transitions

    This feature removes the need to define the commands and states in the FSM config. The FSM will now automatically determine these values from transitions. To further simplify things I the first state is now 'initial' always. This should clarify when writing FSM transitions that everyone knows what the 'initial' state name is. Similar to how nice the 'any' state is.


    opened by ryancurrah 4
  • wip websockets

    wip websockets

    Work In Progress. Initial refactor to support websockets.

    opened by ryancurrah 2
  • configure classifiers and transitions from extensions

    configure classifiers and transitions from extensions

    When connecting to an extension server it would awesome if we could send the bot our own classifiers and transitions. This would allow us to programmatically generate questions and answers.

    An example where this would be used is the company I work at. We have an internal StackOverflow site. We could write an extension that gets all the questions and answers from that site and generate classifiers and transitions and register them with the bot.

    It would be super powerful for automatically training the bot to respond to questions with a set of predefined answers from other tools.

    opened by ryancurrah 7
  • feat: initial stab at a swagger spec for extension server

    feat: initial stab at a swagger spec for extension server

    Ok, I have an initial swagger spec that we can use to generate server implementations for multiple languages.

    View the Swagger Doc here:

    Generated server stubs:

    opened by ryancurrah 3
  • Porting the extension module to other languages?

    Porting the extension module to other languages?

    Hi there! I have had some success following your docs to stand up a Flask app that roughly supports the restful extension API. Very cool project, thank you.

    I couldn't help but be a bit jealous of the Go examples being able to just import extension and run with it.

    I'd like to help make this more accessible for would-be Python, Ruby, JS, etc. bot authors. @jaimeteb have you or @ryancurrah plotted a way to give the rest server API a quicker onramp?

    I've thought about maybe building a python library to abstract a few of the basic bits of the Flask use case, but maybe a swagger-oriented codegen approach could cover more ground with less work. I haven't yet tried the RPC model so I imagine it's got some implications for potential approaches to bootstrapping new REST integrations..

    opened by dpritchett 3
  • rethink how we expose the fsm to extensions

    rethink how we expose the fsm to extensions

    I’ve been thinking about the FSM.Domain and how we pass it to extensions. When I did the internal refactor I felt like FSM package should be a private API.

    Maybe the bot should have some REST APIs for the extension to work with FSM with some safeguards in place. Instead of directly sending the FSM.Domain to the extension. I do feel like this make it less complex for developing new extensions so the extension author does not need to learn how to work with the FSM directly.


    opened by ryancurrah 4
Jaime Tenorio
Mechatronics Engineer with a career in Software Development and Machine Learning. Made in Mexico. 🇲🇽
Jaime Tenorio
💁‍♀️Your new best friend powered by an artificial neural network

??‍♀️ Your new best friend Website — Documentation — Getting started — Introduction — Translations — Contributors — License ⚠️ Please check the Call f

Olivia 3k Sep 21, 2021
Slack Bot Framework

slacker Built on top of the Slack API with the idea to simplify the Real-Time Messaging feature to easily create Slack Bots,

Raed Shomali 554 Sep 16, 2021
A general-purpose bot library inspired by Hubot but written in Go. :robot:

Joe Bot ?? A general-purpose bot library inspired by Hubot but written in Go. Joe is a library used to write chat bots in the Go programming language.

Joe Bot 429 Sep 13, 2021
Flexible message router add-on for go-telegram-bot-api library.

telemux Flexible message router add-on for go-telegram-bot-api library. Table of contents Motivation Features Minimal example Documentation Changelog

Andrew Dunai 15 Aug 20, 2021
The modern cryptocurrency trading bot written in Go.

bbgo A trading bot framework written in Go. The name bbgo comes from the BB8 bot in the Star Wars movie. aka Buy BitCoin Go! Current Status Features E

Yo-An Lin 346 Sep 6, 2021
Simple yet customizable bot framework written in Go.

Introduction Sarah is a general-purpose bot framework named after the author's firstborn daughter. This comes with a unique feature called "stateful c

Go Hagiwara 202 Sep 16, 2021
Telebot is a Telegram bot framework in Go.

Telebot "I never knew creating Telegram bots could be so sexy!" go get -u Overview Getting Started Poller Commands Files Se

Ian P Badtrousers 2.1k Sep 21, 2021
Golang Framework for writing Slack bots

hanu - Go for Slack Bots! The Go framework hanu is your best friend to create Slack bots! hanu uses allot for easy command and request parsing (e.g. w

Sebastian Müller 135 Jul 23, 2021
Telegram Bot Framework for Go

Margelet Telegram Bot Framework for Go is based on telegram-bot-api It uses Redis to store it's states, configs and so on. Any low-level interactions

Gleb Sinyavskiy 63 Jul 27, 2021
Slack bot core/framework written in Go with support for reactions to message updates/deletes

Overview Requirements Features Demo The Name Concepts Create Your Own Slackscot Assembling the Parts and Bringing Your slackscot to Life Configuration

Alexandre Normand 46 Aug 14, 2021
Continuous performance analysis reports for software projects 🤖

Performabot Welcome to Performabot! This little helper can be used to provide Continuous Performance Reports within your GitHub project. But please be

Sascha Grunert 40 Feb 23, 2021
A modern IRC server (daemon/ircd) written in Go.

Oragono is a modern IRC server written in Go. Its core design principles are: Being simple to set up and use Combining the features of an ircd, a serv

Oragono 1.3k Sep 15, 2021
lightning - forward messages between a qq group and a telegram group

lightning The purpose of this project is to forward messages between a qq group and a telegram group. Getting Started Clone this project: git clone ht

方泓睿 5 Aug 6, 2021
A fast cryptocurrency trading bot implemented in Go

A fast cryptocurrency bot framework implemented in Go. Ninjabot permits users to create and test custom strategies for spot markets. ⚠️ Caution: Worki

Rodrigo Brito 852 Sep 13, 2021
A Telegram Repo For Bots Under Maintenance Which Gives Faster Response To Users

Maintenance Bot A Telegram Repo For Bots Under Maintenance Which Gives Faster Response To Users Requests » Report a Bug | Request Feature Table of Con

A tip bot and Lightning wallet on Telegram ⚡️

@LightningTipBot ?? A Telegram Lightning ⚡️ Bitcoin wallet and tip bot for group chats. This repository contains everything you need to set up and run

null 9 Sep 14, 2021