x51 // @kung-fu // max

x51@cyberspace:~$ man max

MAX(3)@kung-fu Library Functions ManualMAX(3)

name

max — a minimalist chatbot framework that works like a true conversation

description

max models a chatbot as a loop of conversational turns rather than a tree of routes. A Bot listens, and each incoming turn flows through middleware to your handler, where the bot can say something, ask a question and remember the answer, or hand the turn to a scripted Dialog. State persists per user in a Memory backed by pluggable storage, and remembered values interpolate into replies with Handlebars-style templates.

Two bots ship with the framework: ConsoleBot runs the conversation on the command line; WebBot exposes it as an HTTP endpoint. Both extend the same abstract Bot, so a bot written against one runs on the other.

classes

classdescription
Botabstract base: listen(), say(), ask(), hears(), use(), on()
ConsoleBot / WebBotcommand-line and HTTP-endpoint implementations
Dialogchainable sequence of ask / say exchanges
DialogSequencenames and orders multiple dialogs
Messagemessage content, attachments, and template interpolation
Memoryper-user state as a Map; load() / save() against storage
Middleware / HearMiddlewareturn-processing pipeline; phrase and regex matching
CacheStoragein-memory storage backend

examples

A console bot that asks for your name once, then remembers it — remember stores the answer in Memory, and {{name}} interpolates it back:

const { ConsoleBot, CacheStorage, Memory, getTurn } = require('@kung-fu/max');
      
      const bot = new ConsoleBot({ name: 'mybot', type: 'console' }, new CacheStorage());
      
      bot.listen(async (conversation) => {
          const turn = getTurn(conversation);
          const memory = await new Memory(bot.storage).load();
      
          if (memory.name === undefined) {
              await bot.ask('What is your name?', { remember: 'name' });
          } else {
              await bot.say('Hello {{name}}, you said: ' + turn.message.text);
          }
      });

A scripted Dialog — the chain runs turn by turn until it completes, then the bot falls through to free conversation:

const dialog = new Dialog(bot)
          .ask('What is your name?', { remember: 'name' })
          .ask('Hi {{name}}, what is your age?', { remember: 'age' })
          .say('Thank you {{name}}!');
      
      bot.listen(async (conversation) => {
          if (!await dialog.continue(conversation)) {
              await bot.say('You said: ' + conversation.turn.message.text);
          }
      });

Pattern matching with hears() — phrases and regexes are checked automatically before your handler runs:

bot.hears('hello', async () => { await bot.say('Hi there!'); });
      bot.hears(/^help/i, async () => { await bot.say('Available commands: help, quit'); });

Or skip remember and handle an answer yourself with a callback:

await bot.ask('Your name?', async (response) => {
          memory.name = response;
          await memory.save();
      });

see also

proto(3), moneta(3)

@kung-fu2026-06-04MAX(3)

x51@cyberspace:~$ cd ~/@kung-fu