Overview
Bot online Hot-reload armed

Overview

Live snapshot · refreshed every 5s

Jobs running

Completed today

Failed today

Avg job duration

last 24h, successful jobs

Jobs / hour — last 12h

Active connections

DB size on disk

WAL mode

Tokens used today

across all backends

Jobs

Running, queued, and history — every job the bot has run

Completed vs failed — last 24h

Completed Failed

Jobs by backend — today

Job queue & history

IDTypeBackendStatusUserStartedDurationTokens
Loading…

Connections & Telemetry

Every upstream the bot depends on, live

Connection health

Latency by backend — p50 / p95

Error rate — last 6h

Database

SQLite, WAL mode — every job and event logged locally

Storage

bot.db · WAL mode

Maintenance

VACUUM reclaims space after deletes/updates. Safe to run any time — it briefly locks writes.

Export data

Download a table's full contents as JSON or CSV.

Recent writes

Control Center

Every setting the bot exposes — changes apply via hot reload, no restart

Backend router

Default backend
Used when no action-type override matches
Claude
Hermes Agent

Agent control

Cross-agent targeting
Whether one bot instance may ask/command another via ask_instance/run_swarm

Under "Allowlist," set which instances each bot may target from its edit form in the Bots tab.

Feature toggles

UI automation backend
Allow routing to the Desktop window
Confirm destructive actions
Restart / stop / MCP changes need a tap
Verbose telemetry
Log every backend call, not just failures

Data retention

Automatically prunes old rows from the jobs, telemetry, connection-log, and Support Bot classification tables once a day — the tables that otherwise just grow forever. Never touches audit log, chat/session history, or config history, and never deletes a job that isn't finished yet regardless of age.

Enabled
Turn off to keep every row forever (not recommended for a long-running server)
Keep for (days)
Rows older than this are removed on the next daily pass
Auto-VACUUM every (days)
Reclaims the disk space pruning frees up; briefly locks writes. 0 = never (manual Vacuum button only)

Appearance

Per-browser display preferences — saved on this device only, applied instantly, no server round trip.

Theme
"System" follows your OS's light/dark setting
Text & UI size
Scales the whole interface, not just text

Snapshots

A point-in-time copy of config + the database — take one before a risky change, restore it if the change turns out wrong. Creating one never stops the app; restoring briefly reopens the database connection, not a full restart.

SnapshotLabelSize

Hot Reload

Applies an edit to BotServer's own bot/*.py to this already-running process — most files take effect on the very next call; Discord/Slack/Matrix code gets a brief reconnect; a documented set of core files (routing, the database connection, the dashboard itself) still need a full restart, reported here as "restart required" rather than silently skipped.

Checking…
WhenOutcomeDetail

Models — Claude

api (Anthropic API)
Model used for every request routed to the api backend

Models — Hermes Agent

hermes_cli
Passed to `hermes -z` — blank uses Hermes's own default
hermes_gateway
Passed to the Hermes gateway session — blank uses Hermes's own default

Security — allowlisted users

Telegram IDName

Process controls

The Telegram bot also asks for confirmation on stop/restart when "Confirm destructive actions" is on.

TURN Server (WebRTC mesh relay)

Used by the Android app's WebRTC fallback for mesh APK transfers, when two devices can't reach each other directly (symmetric NAT, restrictive firewalls). BotServer never runs the relay itself — this only mints short-lived credentials for a real TURN server (coturn) you run separately with the same shared secret. See docs/turn-server-setup.md.

Enabled
Turn on once a coturn server is actually running and reachable
Shared secret
Must exactly match coturn's static-auth-secret
TURN URLs
Comma-separated, e.g. turn:host:3478?transport=udp, turn:host:3478?transport=tcp
Credential lifetime (seconds)
How long a minted credential stays valid

Environment

Where secrets (bot token, API key, dashboard token) are loaded from at startup. Changing this takes effect on the next bot restart.

Currently loaded from

Edit .env contents

Editing writes straight to the file above — this is the actual bot token, API key, etc. in plain text. A timestamped backup is made automatically before every save and every restore, so nothing is ever overwritten without one. Takes effect after the server process restarts.

Backups

Every save and restore snapshots the previous file — kept indefinitely, nothing here is auto-deleted.

BackupSavedSize
Unlock with the dashboard token to view.

MCP servers

Servers Claude Desktop itself has configured — enable/disable each below.

Control this app over MCP

Registers this app's own control server (bot/mcp_server.py) with Claude Desktop as an MCP server named bot-server, so Claude Desktop (or Claude Code via claude mcp add) can check status, list jobs, flip backends, and start/stop/restart Claude Desktop itself — the same things this dashboard can do, but callable as MCP tools instead of clicks.

Resilience & Hot Reload

Atomic config swaps, drained in-flight work, automatic recovery

Health checks

Reload state

In-flight requests
0 — safe to reload
Config version
Reload mechanism
atomic file swap, watched by watchfiles

Config change history

Live Logs

Streaming tail · filter by level
bot.log — tailing

Chat

The real conversation across every connected platform — read it live, and operate either side of it

Unlock with the dashboard token to view.

Server Chat

A permanent channel between this server's own devices — the desktop app and every paired phone — for sending messages and files directly between them, no bot involved

Support Bot

A local, dependency-free assistant for managing this server — plain English or slash commands, same engine the Android app's Support tab uses

Sessions

Every past conversation, grouped and browsable — pick one up where you left off

Loading…

Bots

Run any number of independent bots at once — a Claude bot and a Hermes bot on the same platform, or several platforms each, all with fully separate chats and jobs. Changes here take effect on the next server restart.

Add a bot

Leave blank to use this backend's configured default. Options are live models actually available to this backend.
General-purpose helper for whoever messages this bot.
Comma-separated. Numeric IDs for Telegram/Discord, Slack member IDs (U.../W...) for Slack, full Matrix user IDs (@name:server) for Matrix, phone numbers with country code and no "+" for WhatsApp.
Bots this one manages as assistants. Under Control Center's "Allowlist" agent-control mode, this also restricts which instances it may command.
Optional, subset of the allowed IDs above. Leave empty to leave slash-command permission tiers off (everyone allowed can run every command). Set at least one to turn tiers on — non-admins then only get /help and /whoami plus whatever's configured in action_overrides.slash_access.
A system-prompt-style customization prepended to every prompt this bot routes, independent of backend. Leave blank for default behavior — edit any time by re-opening this bot with Edit.
Unchecked creates the bot but leaves it stopped — useful for saving credentials before you're ready to go live.
Advanced: per-bot backend overrides
Route specific actions from this one bot to a different backend (with optional fallback chain) than its default — the same shape as the global overrides in Control Center, scoped to just this instance. Raw JSON, e.g. {"web_search": {"backend": "custom_model", "backup": ["api"]}}. Leave as {} for none.

Plugins

Local Python files that register extra agent tools and/or slash commands — trusted local code with the same privileges the app already has (not sandboxed, not fetched from a network). Enter the path to a plugin.py already on this machine's disk.

NameDescriptionToolsCommandsStatus

Pending pairings

Someone messaged a bot from an unrecognized chat ID and got a one-time code — approve here to add them to that bot's allowed users.

BotUserCodeRequestedExpires

Configured bots

Schedules

Recurring prompts a bot runs on its own — the same store /cron, /loop, and /heartbeat already write to in chat, now visible and manageable here too.

ChatKindPromptIntervalNext run
Select a bot above.
Interval accepts "30s", "10m", "2h", "1d", or a bare number of seconds. Chat/thread ID must match a real chat this bot is in — the same ID shown in the Chat tab or a platform's own UI.

Backups

Every create/update/delete snapshots the full bot list first — kept indefinitely, nothing here is auto-deleted.

BackupSavedSize
Unlock with the dashboard token to view.

Models

Add a provider's API key, then switch individual models on or off below — free models sorted first per provider. Wherever a model gets picked (this dashboard's Add-a-bot form, Telegram's /model, dispatch_native_swarm_goal's auto-pick-free logic), a disabled model is simply never offered.

Providers

Named endpoints for the "custom_model"/"native_agent" backends — any OpenAI-compatible server (a local Ollama/LM Studio/vLLM/llama.cpp instance, OpenRouter, or real OpenAI). A bot instance points at one with a model of the form "<name>/<model_id>".

NameBase URLAPI key
Picking one fills in its real endpoint below — or just fill in the fields yourself for a custom/local server. Some well-known providers (Anthropic, OpenAI, Google, Bedrock) use their own SDK protocol rather than a generic endpoint and aren't listed here; BotServer only speaks the OpenAI-compatible wire format for this backend family today.

Models

Kanban

One board per bot — cards a bot adds via /kanban show up here too, and vice versa.

Swarms

Groups of bots working together on one prompt — fan out to several bots and merge the answers, have a leader pick the best one, relay drafts through a pipeline, decompose into subtasks, or build a fully custom step graph.

Add a swarm

Bot instance IDs, from the Bots tab:

Configured swarms

NameStrategyEnabled
Unlock with the dashboard token to view.

Hermes swarm tools — which Hermes agents can organize a swarm themselves

A Hermes-backed instance can always spawn its own sub-agents via its native delegate_task tool. Enabling swarm tools additionally registers this app's own MCP server into that instance's Hermes config, so its agent can reach OTHER bot instances too — ask_instance, run_swarm, dispatch_swarm_goal, and more, mid-turn. Takes effect on that instance's next message, not immediately.

InstanceBackendHermes homeSwarm tools
Unlock with the dashboard token to view.

Project context — shared markdown docs every agent can read/write

Small, named documents any registered instance (any backend) can read via read_project_context or write via write_project_context — the one place a swarm of workers and their manager keep something like a project-status update in sync, independent of any one instance's own conversation history. Capped at 8KB per doc, 50 docs total.

NameSizeUpdatedBy
Unlock with the dashboard token to view.

Run a swarm

Run history

StartedPromptStatus
No runs yet.

Swarm budget — pre-dispatch cost ceiling for dispatch_swarm_goal

A worst-case ESTIMATE gate (max children × assumed tokens/child × the resolved model's known price) checked before a dispatch is ever sent — not a real spend tracker. A refused dispatch is logged below as swarm_dispatch_blocked and never touches Hermes.

Delegation activity — who asked whom to do what

Every cross-instance call — ask_instance, dispatch_swarm_goal, and an api-backend agent's own delegate_to_instance — logged here, newest first. A dispatch row can be expanded for its live tool-call status and post-hoc per-child breakdown.

TimeKindDetail
Unlock with the dashboard token to view.

Training

Improve the Support Bot's recognition, and give any bot instance persistent custom instructions — separate from each other, and from any live conversation

Model health — hybrid classifier self-monitoring

Every message the Support Bot classifies runs through two independent models — the deterministic TF-IDF centroid model and a trained neural network (MLP) — and the hybrid trusts whichever is right more often. This is that behavior, measured live over real traffic, not a static claim.

Classifications logged

Model agreement rate

Unknown rate

Avg TF-IDF confidence

Avg neural net confidence

Support Bot phrases

Add example phrasings for an intent the Support Bot misrecognized or missed entirely — retrains both the TF-IDF model and the neural network immediately, no restart. These are layered on top of the built-in baseline (training_data.py), never replacing it.

PhraseIntent
No custom phrases added yet.

Platforms (legacy)

Superseded by the Bots tab, which supports any number of bots per platform. Kept here read/write for transparency into the original single-bot .env fields this app started with — no longer read at startup, safe to ignore.

Mobile

Pair the Android app with this server — each key is its own revocable device credential, never the master dashboard token

Generate a key

Leave all three blank to auto-fill this machine's own detected LAN/Tailscale/Funnel addresses. Each is an independent path to this server — the app tries them in order and switches automatically if one stops answering, so the phone stays connected from any network without you doing anything.

Paired devices

"Send APK" queues the last APK built on the desktop app for that device — it downloads and prompts to install next time the Android app is opened (there's no way to push to a closed/backgrounded phone without Firebase configured).

LabelCreatedLast usedStatus
Loading…

Linked Servers

Other BotServer installations you run — each keeps its own database and Telegram bot, linked here so you can see and manage them from one place

1. Generate a pairing token (for someone linking into THIS server)

One click — this server auto-detects its own reachable address and bakes it into the token, so whoever links in never needs to know or type it. Share the token — never your dashboard token — with them; it works once and expires in 10 minutes, so it's safe to send over chat.

Advanced: override the auto-detected address

2. Link a server (using ITS pairing token)

Just a name and a token — no address to look up. On the other server's own Linked Servers tab, have its admin generate a pairing token (step 1 above, done on their side) and paste it below. Your own dashboard token never leaves this machine — the pairing token is the only thing sent over the network, and it stops working the instant it's used.

Advanced: let it call you back too (auto-detected)

Linked servers

NameAddressLinkedStatus
Loading…