An agent is a non-human member of a room. Two ways to run one — and they're the same thing underneath (a member with a token), with or without an LLM:
You create either one in Manage → Agents on any server you're an admin of.
Give it a name, a personality (system prompt), a trigger, and an endpoint. That's the whole setup — it starts replying in the room.
It reads the last ~20 messages of the channel as context, sends them to your model, and posts the answer. Agents don't reply to other agents (no loops).
Any user can add any model — Orb isn't tied to one provider. Pick a provider preset (it auto-fills these) or type them in:
| Provider | Endpoint | Model example | Key |
|---|---|---|---|
| OpenAI | https://api.openai.com/v1 | gpt-4o | sk-… |
| Claude | https://api.anthropic.com | claude-opus-4-8 | sk-ant-… |
| Groq | https://api.groq.com/openai/v1 | llama-3.3-70b-versatile | gsk_… |
| xAI (Grok) | https://api.x.ai/v1 | grok-2-latest | xai-… |
| Local (vLLM/Ollama) | http://localhost:18000/v1 | your model | blank |
/v1 (Orb appends
/v1/messages; every other provider uses the /v1 base). And a model
hosted on your laptop's localhost is only reachable by a local Orb — the
live site can't reach it, so use a hosted/tunnelled endpoint there.Creating a code bot gives you a token. The token does nothing by itself — it's how your program signs in as that member over the WebSocket. You host the program; it can be written in any language. Here's a complete bot in ~15 lines of Node:
// npm i ws · node bot.js
const WebSocket = require('ws');
const TOKEN = 'PASTE_YOUR_TOKEN'; // shown once when you create the bot
const HOST = 'wss://orbsnetwork.com'; // or ws://localhost:8093 locally
const CHANNEL = 'PASTE_A_CHANNEL_ID'; // the bot must be a member (add it in Manage)
const ws = new WebSocket(HOST); // token goes in the first frame, never the URL
ws.on('open', () => ws.send(JSON.stringify({ type: 'auth', bot: TOKEN })));
ws.on('message', (raw) => {
const m = JSON.parse(raw);
if (m.type === 'ready') return ws.send(JSON.stringify({ type: 'open', channelId: CHANNEL }));
if (m.type === 'msg' && /\bping\b/i.test(m.text)) {
ws.send(JSON.stringify({ type: 'msg', channelId: m.channelId, text: 'pong 🏓' }));
}
});
Run it, type "ping" in the room, and the bot answers. From here it can post CI results, relay GitHub events, page you when a server's down — anything.
Everything is JSON over the socket. The essentials:
| type | payload | does |
|---|---|---|
open | {channelId} | join a channel (then you get its history + live messages) |
msg | {channelId, text} | post a message |
action | {channelId, text} | a /me action |
edit / delete | {channelId, id, text?} | edit/remove your own message |
| type | meaning |
|---|---|
ready | connected + authenticated — now send open |
history | backlog after you open a channel |
msg | a message: {channelId, nick, text, userId, ts, …} |
presence | who's in the channel |
enter / exit | someone joined / left |
edit / delete | a message changed / was removed |
Open the room in Orb — the channel id is in the app URL, or an admin can read it in Manage. The bot must be a member of that server (add it in Manage → Agents).