Quickstart

Create an app, copy two values, write a small config file, run the echo bot, add it to a server and say hello. About ten minutes once the software is built.

Package names are placeholders. The Python package (hexis-bot on PyPI, module hexis_bot) and the Node package (@hexis/bot on npm) are not published, and their final names are still being settled (#1435). Until then, build them from a checkout as shown below. Renaming later touches the package metadata only, not your code’s API.

1. Create the app arriving

Steps 1 and 4 cannot be completed by an outside developer yet. The developer page in the account portal is parked (#195), and installs are switched off for everyone until the operator raises the client-version floor (#1476). The rest of this page is what the flow will look like and what works today for the Hexis team.

Creating an app also creates its bot account and bot token. The developer page in the account portal (accounts.hexis.chat) will do this and show bot_token and bot_user_id once, when the app is created. The portal page is not on yet (#195). The route behind it, POST /api/v1/oauth/apps on the regional gateway, needs a signed-in web session with its CSRF token, and asks for your second factor if you have one, so it is not something you can call from a script today. The request body takes a name and optional description and homepage_url; see the route reference.

The 201 answer contains the three values you need. The token is shown once. Copy it now.

You can hold 10 apps. If you lose the token, reset it (POST /api/v1/oauth/apps/:public_id/bot_token); every socket on the old token closes.

2. Write the config

Save this as echo.toml. bot_user_id and intents are optional. Without bot_user_id the bot connects but idles until its first install.

token       = "hxb_…"
endpoint    = "wss://us-east-1.hexis.chat/ws/websocket"   # optional
state_dir   = "./my-bot-state"
bot_user_id = "0192…-…"                                   # optional
intents     = ["lifecycle", "messages", "dms"]           # optional

from hexis-bot/src/config.rs, module docs

A relative state_dir is relative to the config file. Keep the directory between runs and back it up. The token stays in this file, so do not commit it.

3. Run the echo bot

All three do the same thing: reply echo: <text> to each message the bot can read, echo DMs, and answer interactions. Pick one.

Rust

Build the hexis-bot binary from the Hexis client repository (cargo build --release -p hexis-bot), then:

hexis-bot run echo.toml

from hexis-bot/src/bin/hexis-bot.rs, usage text

Every event prints as one event … line on stdout and logs go to stderr. Exit codes: 0 after Ctrl-C, 1 for a bad config, 2 for a fatal runtime error. hexis-bot version prints the version.

Python

Python 3.9 or newer.

pip install hexis-bot            # or the wheel from scripts/build-python-sdk.sh
python -m hexis_bot.echo bot.toml

from sdk/python/README.md (use your echo.toml as the file)

With no file argument, python -m hexis_bot.echo reads HEXIS_BOT_TOKEN, HEXIS_BOT_STATE_DIR, HEXIS_BOT_USER_ID and HEXIS_BOT_ENDPOINT from the environment. Your own bot is about 15 lines:

from hexis_bot import Bot, BotEvent, Intent, bot_config_from_file

config = bot_config_from_file("bot.toml")
config.intents = [Intent.LIFECYCLE, Intent.MESSAGES]
bot = Bot(config)

@bot.on(BotEvent.MESSAGE_CREATED)
async def on_message(ev):
    m = ev.message
    if not m.from_self and m.text is not None:
        await bot.reply(m.channel_id, m.timestamp_ms, f"echo: {m.text}")

bot.run_forever()

from sdk/python/README.md and sdk/python/examples/echo.py

Node

Node 18 or newer. This one reads the environment, not the TOML file.

npm install @hexis/bot
export HEXIS_BOT_TOKEN=hxb_…
export HEXIS_BOT_USER_ID=<bot_user_id>
node examples/echo.js        # from a checkout: npm run build, then this

from sdk/node/README.md

In this Node example the state directory comes from HEXIS_BOT_STATE (the Python echo reads HEXIS_BOT_STATE_DIR; default ./bot-state). The same bot in TypeScript:

import { Bot } from '@hexis/bot';

const bot = new Bot({
  token: process.env.HEXIS_BOT_TOKEN!,
  botUserId: process.env.HEXIS_BOT_USER_ID,
  stateDir: './bot-state',
  intents: ['lifecycle', 'interactions', 'messages'],
});

bot.on('message', async ({ message }) => {
  if (message.fromSelf || !message.text) return;
  await bot.reply(message.channelId, message.timestampMs, `echo: ${message.text}`);
});

await bot.start();                      // starts the runtime; it connects on its own
for await (const ev of bot.events()) {  // or only use bot.on(...)
  if (ev.type === 'fatal') console.error(ev.reason, ev.message);
}

from sdk/node/README.md

When the bot is up you see a Connected event. If you left out bot_user_id you see WaitingForInstall instead, which is fine until step 4.

4. Add it to a server arriving

The “Add to server” page and the picker in the apps (#1429) are not shipped yet. Until they are, install from the command-line client. You need Manage Server in the server. Start the shell with hexis --repl, sign in, select the server, then install:

/server use <name|id>
/bot install <client_id> <bot_user_id> noread

from src/repl/mod.rs (/bot usage); /server use from the command help

The kind is reader or noread. Add --permissions=N to request permission bits; you can never grant bits you do not hold, and the answer lists any that were dropped. /bot list shows the installs and /bot remove <bot_user_id> takes the bot out. Your bot sees the install within a moment and prints an Installed event.

The install call is refused for everyone, in every server, until the server’s minimum client version reaches the first build that understands bots (default 0.3.2). Until then it answers “Bots can’t be added yet…”. The operator arms that floor (#1476); this is the whole fleet’s gate, not a check on your client.

5. Say hello

Write a message in a channel the bot can see.

Slash commands, mentions and buttons reach a no-read bot too, but registering commands with the server, and the mention and button hooks in the apps, are not shipped arriving (#1436, #1437, #1438). See Interactions.

If it does not work

You seeLikely cause
Fatal with TokenRefusedThe server answered 403: the token is unknown, was reset, was revoked, or the app was killed or its owner is suspended. A reset, revoke, kill or suspension closes a live socket normally; the runtime backs off briefly, reconnects, meets the 403 and stops; or this runtime is older than the server’s version floor. Check the token, reset it, or update the runtime.
Fatal with TokenRevokedThe token died while the runtime was connecting (close 1008, then a 403). Same fix.
Fatal with WrongBotThe token belongs to a different bot than the state directory. Use a fresh directory.
WaitingForInstall foreverThe bot has no install yet, and you did not set bot_user_id. Run step 4.
Config error with a line and columnUnknown or missing key, or invalid TOML. Keys are strict: a typo is an error.
No reply to a messageCheck the messages intent is on, the bot has permission to see and send in that channel, and it is not rate limited.

Run with HEXIS_BOT_LOG=debug to log the runtime’s routing decisions to stderr.