Bot Instances

Running your own Hummingbot market makers on the platform server — detection, provisioning, the diagnostic doctor, the desired-state supervisor, memory ceilings, crash diagnosis and live logs, with no terminal.

9 min readUpdated 3 August 2026instances, supervisor, provisioning, doctor, logs, market-making

Admin → Hummingbot → Bot Instances runs Hummingbot on the platform server itself and controls it from the browser. Register a checkout once and from then on start, stop, restart, diagnose, reinstall the connector and read live logs without opening a terminal.

This is for your own market making — providing liquidity on your own books. Your users are unaffected; they continue to run Hummingbot on their own machines against their own API keys, and both models work at the same time.

One Hummingbot process costs roughly 400–700 MB of RAM for a single connector on one pair, and up to about 1.2 GB for XEMM, which runs two. That server is already running your database, Redis, the backend, the frontend — and ScyllaDB if Ecosystem is installed. A handful of your own bots is comfortable; one per user is not, and when the host runs out of memory the kernel may pick your database rather than a bot.

Before you start

Hummingbot has to exist on the server. The panel supervises a checkout; it can fetch the source for you, but it cannot complete the build inside an HTTP request. Two values identify an install:

Value Example
Install path — the checkout root, containing hummingbot/ and bin/ /home/user/hummingbot
Python interpreter — the conda environment's python /home/user/miniconda3/envs/hummingbot/bin/python

The backend process does not inherit your shell's PATH. A bare python resolves to whatever the service user happens to have — frequently the wrong environment, or Python 2.7, or nothing at all.

Detection and provisioning

Opening Add instance runs a detection pass first. It searches a bounded set of locations — a fixed list of roots, one level of expansion, never a recursive disk walk, because it runs synchronously inside an admin request on a production server. It offers what it finds with an origin and a confidence, so a wrong pick is obvious, and it pre-fills the exchange URL from the address you are browsing and sizes the memory limit against the host's free memory.

A candidate that would land on the connector kit shipped with the platform is rejected rather than offered. <platform-root>/hummingbot is the obvious guess and is exactly where the kit lives, so that flag is what stops the panel handing you a path the doctor is guaranteed to reject.

If nothing is installed, Provision prepares a location:

Action Does
Check Validates the target path only — nothing is written
Create Creates the directory
Install Creates it and clones the Hummingbot source into it

It refuses filesystem roots, the platform's own directory and public web roots, and requires roughly 2 GB free. It then prints the exact remaining command rather than pretending to run a ten-minute Cython build inside a web request:

cd /path/to/target && ./install && conda activate hummingbot && ./compile

conda activate has to happen between the two: ./install creates the environment and ./compile must run inside it.

On a Windows host there is no runnable command, because ./install is a bash script and Hummingbot's source build is not supported natively on Windows. The panel says so, and offers to provision into a WSL distribution instead. It also lists running VMware guests, because WSL 2 needs Hyper-V and Hyper-V costs VMware Workstation its acceleration, so operators running Linux in Workstation usually have WSL unavailable. Both listings are about where to build: a bot is always run by the configured interpreter on the host itself.

Registering an instance

Nothing starts on save. desiredStatus defaults to STOPPED so you can diagnose the configuration before a bot ever touches the book.

Field Meaning
Name A label, e.g. "BTC-USDT market maker"
Strategy preset A preset from the Strategy Studio. Its YAML is regenerated into the checkout on every start
Market Chosen from the real market list, not typed. Overrides the preset's own pair
Install path Absolute path to the checkout
Python interpreter Absolute path to the environment's python
Trading credentials The API key this bot signs with — pick one or mint one from the form
Exchange base URL The URL the connector dials, normally this deployment's own public URL
Config password Hummingbot's own password, which decrypts its stored connector credentials
Memory limit The bot is killed above this. Default 1536 MB. Enforced on Linux
Auto-restart Restart after a crash, with backoff

The market has to exist

Registering or starting an instance whose market the exchange does not list is refused, with the pairs that do exist. Previously this produced the worst kind of failure — a completely successful start: the connector was created, the process stayed alive, the panel showed RUNNING, and the bot logged bicrypto is not ready. Please wait... forever without ever quoting, because its book never arrived.

The check runs again at start, because a market can be delisted between choosing it and running. On an install without the Ecosystem addon the market list cannot be read, so the check yields nothing and starting is allowed — refusing on the basis of a list that cannot be seen would be worse than the hang it prevents.

Trading credentials

Hummingbot will not trade a connector it has no keys for, and it keeps those keys inside its own install rather than reading yours — so the supervisor writes them there at start time from whatever is selected here. Without a key the bot loads its strategy and then exits.

A key minted from this form is scoped to what a market maker needs and no more — read balances and markets, place and cancel orders of the relevant type, and for perpetuals manage its own positions. Never key-management scopes, so a leaked secret cannot mint more keys. The secret is written straight into the Hummingbot install and never returned to the browser.

The config password

Hummingbot's one-time config-password step only exists on its interactive path: login_prompt() walks a user through creating conf/.password_verification, and there is no equivalent under --headless, so a fresh checkout dies with a raw FileNotFoundError. The panel performs that step before launch.

That file is also the only way to detect a wrong password, because every encrypted connector key under conf/connectors/ is sealed with the same secret. Rewriting it on a mismatch would turn "you typed the wrong password" into "every API key you saved is now permanently undecryptable", silently. A mismatch is reported and you decide.

The stored password is encrypted at rest with a key derived from APP_ACCESS_TOKEN_SECRET, domain-separated from anything else that secret protects, and passed to the child process through its environment — never through argv, which is world-readable in ps on most Linux hosts. Rotating that secret invalidates stored passwords; the panel detects it and asks you to re-enter, rather than failing the bot with an obscure error.

Diagnose before you start

Diagnose tests the real server, right now, and reports each check with what was found and how to fix it:

Check Catches
Hummingbot install path The directory exists and is genuinely a checkout
Launcher script Which entry point will be used
Python interpreter It runs, and which version it is
Hummingbot importable That this interpreter and this checkout are a matching pair
Bicrypto connector Installed, and not nested
Config directory Exists and is writable — the panel writes controller YAML into it
Launcher capabilities Which options this build supports, probed rather than assumed
Headless mode Whether this build accepts it
Memory headroom Free memory against this instance's cap

A fail blocks startup; a warn does not. "Hummingbot importable" is the one that earns its place: a valid-looking path paired with a valid-looking python from a different environment passes every other check and fails only at launch.

If the connector check reports a nested package, use Reinstall connector — it runs the installer shipped with your platform, including the clean mode that wipes the target directories first.

This is the environment check for a server-run install. The connector installer's own --doctor mode is a separate check, for whether connect bicrypto will appear inside a given checkout.

Start, stop, restart

The buttons record intent. A supervisor loop converges the real process towards it within a couple of seconds — which is why a card may briefly read Starting or Stopping, and why pressing a button twice is harmless.

Status Means
Running The process is alive and supervised
Starting Diagnosis passed and the process is being launched
Stopping SIGTERM sent; the bot is winding down
Stopped Not running, deliberately
Crashed It exited on its own, or failed to start. The reason is on the card

Stopping is graceful: SIGTERM and 20 seconds to cancel resting orders before it is forced. Killing a market maker instantly would leave live orders on the book with nothing managing them.

Restart regenerates the controller YAML from the linked preset, so it is also how you roll out a strategy change. Configuration is read at launch, so editing an instance while it runs does not affect the live process — the panel prompts you to restart.

Auto-restart backs off: a bot that dies is restarted after 5 seconds, doubling to a ceiling of 5 minutes; ten minutes of healthy uptime resets it. A bot that can never stay up stops consuming the host.

Why it is desired-state, not direct execution

Admin routes never spawn anything. They write the desired status on the row and return; one reconciler loop converges reality towards it. Three consequences you can rely on:

  • One bot per instance, never two. Within a backend process — across every one of its worker threads — exactly one reconciler loop runs. Otherwise each worker would launch its own copy of every bot against the same account: two market makers quoting the same book, neither aware of the other's inventory. Two backend processes on one host is not a supported topology, but it does happen — an orphan that outlived a restart — and there the in-process guards cannot reach, because the database row is all the two share. So the right to launch is taken with a single atomic statement on that row. The process that loses it starts nothing and writes a line to the instance log naming the duplicate-backend condition, which is your cue to go and find the orphan.
  • Start and stop are idempotent. A double-clicked button, a retried request or a request that times out mid-spawn all converge to one outcome.
  • It survives a deploy. A bot you asked to run comes back after a backend restart instead of staying silently dead, and a process that outlived the restart is re-adopted — verified as the bot it recorded before adopting it — rather than started a second time alongside itself. Live log capture for a re-adopted process only resumes after a restart.

Safety model

A panel that runs programs on your server deserves scrutiny. Precisely what it can do:

  • There is no command box. The browser sends an intent from a fixed set — start, stop, restart, install, diagnose — which the server maps to a hard-coded argument array.
  • Nothing reaches a shell. Arguments are passed directly to the process, so quoting and shell metacharacters in a path cannot become a command.
  • The installer path is fixed. "Reinstall connector" runs the installer shipped with your platform and cannot be pointed at another script.
  • Permission-gated. Viewing needs view.hb.instance; start, stop and restart need manage.hb.instance; editing and reinstalling need edit.hb.instance; registering, provisioning and minting a key need create.hb.instance; removal needs delete.hb.instance.
  • Audited. Every start, stop, restart, edit and install is written to the instance log with the administrator who requested it.

Logs and crash diagnosis

Logs streams the process output, per run, newest last, colouring errors and warnings. Lines tagged [supervisor] come from the panel itself — start and stop requests, install runs, crash reasons and memory kills. Logs are written to disk, so the final output of a crashed bot survives a backend restart, which is exactly when you most want to read it.

Repeated lines are throttled after the third occurrence, with a periodic marker so time is still visible. Hummingbot's MQTT bridge retries every five seconds for the life of the process and is unavoidable in headless mode, so it is filtered as noise; nothing in the panel depends on it.

When a supervised bot exits, the card names a probable cause and the next action instead of "exited with code 1". Known Hummingbot failures are matched by name — no saved keys for the connector, a missing interpreter, a config it would not accept — each with the fix. Pure consequence lines such as Exiting. are never reported as the cause, which is what made "read the logs" mean "read past four lines of noise".

Memory ceilings

Each instance carries a hard limit, default 1536 MB. A bot over it is killed and the reason is recorded on the card. A runaway bot must die on its own rather than let the kernel pick a victim, which on this host could just as easily be MySQL or the backend itself.

The watchdog reads live memory usage from the operating system, which is available on Linux. On other platforms the cap is recorded but not applied, and the panel says so rather than implying protection it does not have.

Deleting an instance

Deleting a running instance is refused unless you confirm, because a process with no record is one nothing can ever stop. Stop it first.