InfiArtt Developer Center · Developer space · InfiTalk bot catalog
InfiTalk bot documentation
Make your own InfiTalk bot: it runs on your computer and reaches every server it was added to through one WebSocket connection. It can write, answer commands, open dialogs that work well with screen readers, and play audio.
Quick start
- Make a bot on Developer space
and copy its token (it starts with
itw_). The token is shown once. Never share it or put it in a public repository. - Add the bot to a server you manage with "Add to a server" on the same page. Your own bots need no review.
- Download an example and run it with your token:
- echo-bot.js (Node.js 22+, no packages)
- echo_bot.py (Python 3.9+,
pip install websockets)
INFITALK_TOKEN=itw_... node echo-bot.js
# PowerShell
$env:INFITALK_TOKEN="itw_..."; node echo-bot.js Python SDK
For bigger bots, use the official InfiArtt SDK infitalk (Python 3.10+, MIT license). It takes care of the connection, resume, the 3-second rule, dialogs, buttons and audio, and has a local tester that needs no server.
pip install git+https://github.com/InfiArtt/infitalk-python
from infitalk import Bot
bot = Bot() # INFITALK_TOKEN
@bot.command("echo", "Repeat what you write")
async def echo(ctx, text: str):
await ctx.respond(text, public=True)
bot.run() The example has a menu (Ctrl+Shift+P in InfiTalk) with an echo command, a hello dialog and a quiet one-second tone.
Connecting to the gateway
The address is wss://tt.infiartt.com/bot.
Every message is one JSON object in one WebSocket text message.
- The gateway says hello:
{"op":"hello","gateway":1,"heartbeat_interval":30000} - The bot sends its token within 10 seconds:
"resume" may be empty. It holds the session and the last event number per server from the previous connection.{"op":"identify","token":"itw_...","resume":{"12":{"session":"...","seq":340}}} - The gateway answers:
{"op":"identified","bot":{"id":7,"name":"echo"}, "servers":[{"server":12,"name":"Kafe Musik","awake":true}], "limits":{"messages_per_second":200,"audio_streams_per_server":2,"max_message":1048576}} - Send
{"op":"heartbeat"}at least everyheartbeat_intervalmilliseconds. The answer is{"op":"heartbeat_ack"}. The gateway keeps the line to every server alive itself, so no heartbeat per server is needed.
If the connection drops, connect again with "resume". Servers keep the bot for 60 seconds and the last 1000 events (2 minutes), so nothing is lost and people do not see the bot leave and come back.
Servers
One connection serves every server the bot was added to. Every message from and to a server carries "server".
ready: the server is awake and the bot is in. It has the bot's user id, the channels it may see, its permissions, the session and "resumed".server_sleeping: the server went to sleep because nobody is on it. The gateway connects again by itself when it wakes, then a new "ready" comes. Bots do not keep a server awake.server_added/server_removed: the bot was added or removed on infiartt.com (within a minute).
{"op":"say","server":12,"channel":5,"content":"Hello!"} What a bot sends
Every request may carry "ref". The answer is {"op":"result","ref":...,"ok":true|false,"error":...}.
| Op | Use |
|---|---|
join | channel or path; 0 to leave; "everywhere":true to be in every channel (needs approval) |
say | a message in a channel: channel, content, reply_to, actions (buttons and a choice) |
edit / delete | the bot's own messages (msgid) |
pm | a private message, only to someone who wrote to the bot or named it in the last 10 minutes |
commands | the bot's menu (up to 250 commands) with categories, fields and permission (everyone, moderator, admin) |
respond | an answer for one person, or for the channel with "public":true |
defer | "working on it", when an answer takes more than 3 seconds |
suggestions | suggestions while someone types in a field with "suggest" |
dialog, dialog_update, dialog_close | dialogs from JSON (see below) |
audio, audio_end | audio (see below) |
status | status text such as "Playing: ..."; may be per channel |
allowed | may this person use that command (for commands typed in the chat) |
channel_info | who is in a channel, its name and path |
{"op":"commands","server":12,"commands":[
{"name":"echo","description":"Repeat what you write","category":"Fun",
"options":[{"name":"text","label":"Text","type":"text","required":true}]},
{"name":"stop","description":"Stop the music","permission":"moderator"}]} Events a bot receives
command: someone used the menu. It hasinteraction,command,values,user(withlevel),channel.action: a button or choice on a bot message was used.form,suggest,dialog_event: a form was filled in, someone is typing in a field, or something happened in a dialog.message: a message that names the bot (mentions), or every message (messages).direct: a private message to the bot.member: someone joined or left a channel (members).
The 3-second rule: every interaction must be answered within 3 seconds with respond, defer, dialog or dialog_update, else the person hears that the bot did not answer. An interaction can be answered for 15 minutes after defer.
Dialogs
Dialogs are made from JSON and shown by the client as real Windows controls, so they work with NVDA and JAWS. Controls: label, text, number, checkbox, radio, select, slider, list, button and group.
- Every control except label needs a label. The server refuses dialogs without labels.
- An & in a label gives the Alt letter. If it is missing or taken, the client picks one.
- At most 100 controls, 200 options per control, 64 KB.
dialog_updatereplaces controls in place without closing the dialog;"announce"is read by the screen reader.
{"op":"dialog","server":12,"interaction":881,"dialog":{"id":"eq","title":"Equalizer","focus":"bass",
"controls":[
{"type":"slider","id":"bass","label":"&Bass","min":-12,"max":12,"step":1,"unit":"dB","value":0,"notify":true},
{"type":"select","id":"preset","label":"&Preset","options":[{"value":"flat","label":"Flat"},{"value":"pop","label":"Pop"}]},
{"type":"button","id":"save","label":"&Save","default":true},
{"type":"button","id":"close","label":"Close","close":true}]}} Audio
- Format: PCM 48 kHz, stereo, 16-bit signed little-endian, base64 encoded. The server turns it into the channel's Opus.
- Send in real time, for example 20 ms pieces (3840 bytes) every 20 ms. The server keeps up to 3 seconds.
- The bot must be in that channel (join) and allowed to speak there.
- At most 2 audio streams at once per bot per server. Member servers play in at most 7 channels at once.
audio_endplays out what is buffered and stops;"drop":truestops at once (stop, skip).- Keep the volume reasonable. Listeners have their own volume for bots, but loud audio still hurts.
{"op":"join","server":12,"channel":5}
{"op":"audio","server":12,"channel":5,"pcm":"AAAAAP7/..."}
{"op":"audio_end","server":12,"channel":5} Permissions
A bot asks for permissions when it is made. Server owners see them on the consent screen and may give fewer. Without the needed one, a request gets missing_permission.
mentions: messages that name the bot or answer a message of the bot.direct: private messages sent to the bot.send: write messages in channels and answer for the whole channel.manage_own: change and delete the messages the bot wrote itself.speak: send audio to channels, for example music.dialogs: open windows with buttons, lists and sliders for the person who uses it.commands: have a command menu (Ctrl+Shift+P) people can use.everywhere: the bot shows in everyone's channel without join or leave sounds, and can play audio in several channels at once (a music bot, for example). Never in private channels.messages: every message in channels the bot may read, never from private channels. Needs a clear reason. (privileged permission)members: who joins the channels the bot may see. (privileged permission)presence: see who is online on the server. Not used yet. (privileged permission)
A bot never gets private messages between two people, private channels that do not allow it, passwords, IP addresses or device ids.
Limits and error codes
- Messages up to 1 MiB. At most 200 messages a second per bot (bursts up to 400).
- Channel messages: 5 per 5 seconds per channel and 50 a minute.
- At most 20 connections from one address, and 30 identify attempts a minute.
| Code | Meaning |
|---|---|
| 1001 | the gateway restarts or infiartt.com cannot be reached; connect again |
| 1009 | message too big |
| 4001 | no identify within 10 seconds |
| 4002 | invalid WebSocket frame |
| 4004 | the token is not valid, was changed, or the bot was turned off; do not connect again with it |
| 4005 | the same bot connected somewhere else |
| 4008 | too many messages |
| 4009 | no heartbeat |
Errors in "result": identify_first, unknown_server, server_asleep, rate_limited (with retry_after), too_many_streams, missing_permission (with permission), not_in_channel, not_allowed, invalid_token, bad_json.
The last error and the last connection time of a bot are shown on Developer space.
Catalog and rules
Bots sent to the catalog are reviewed by the InfiArtt team before every server owner can add them. Before sending: a description in Indonesian and English, a help page, a privacy policy, and the bot has connected at least once. The review checks:
- The bot is on, answers within 3 seconds, and all its commands work
- Its menu, dialogs and messages were tried with NVDA: every control has a label, Alt letters make sense, texts are not too long to be read
- The permissions fit what it does, and privileged ones have a reason
- The help page and privacy policy exist and are clear
- No spam, harmful content or disturbing audio
A bot that asks for new permissions leaves the catalog until it is reviewed again; servers that added it keep the old permissions. Bots that break the rules (spam, collecting data without consent, disturbing audio) are turned off.