Skip to content

hives

A hive is a kind. A bee is a running instance of it. This page is both the catalogue of reference hives and the guide to building your own.

The vocabulary, once

A nest is the space inside a humd where bees gather and cells live. A hive is the kind, such as claude-cli, openai-server, or paid-oracle. It does not run on its own; it is a typology plus a binary. A bee is the running instance a hive commissions. A worker produces compute: it accepts chi:"prompt" and emits chunk then finish. A forager translates an outside wire into thrum, whether that wire is HTTP, SMS, a smart contract, or a paid API. A bee can be both. While a bee is mid-handshake it is a nestler, and once registered it is nestled.

A bee is just a process that handshakes with a humd over thrum. The handshake is the registration. Once it completes, humd knows the bee exists, what chi it speaks, and how to route to it. humd never links a hive in at build time; bees attach at runtime, in any language.

Catalogue

hiverolebinarywire it speaks
claude-cliworkerclaude-cli-workerclaude -p stream-json over a pipe
claude-replworkerclaude-repl-workerclaude REPL over a PTY
humfsforagerhumfs-foragerlocal filesystem (fs capability)
openai-serverforageropenai-serverOpenAI /v1/chat/completions
anthropic-serverforageranthropic-serverAnthropic /v1/messages
ollama-serverforagerollama-serverOllama /api/chat
vercel-aiforagervercel-aiVercel AI SDK LanguageModelV3
paid-oracleforagerpaid-oraclex402 over tool-call, USDC per call
grpcforagergrpc-foragergRPC bidi stream
twilio-smsforagertwilio-smsTwilio Messaging webhook
gsm-modemforagergsm-modemGSM AT-command serial SMS
bp7foragerbp7-foragerBundle Protocol v7 (DTN)
commonlibraryn/aserve_worker / serve_forager plus identity

Listing here is editorial, reserved for exemplars the maintainers keep. Your hive works the moment it handshakes a humd, whether or not it lives in this repo.

Propensity, the three axes of a bee

Every bee sits somewhere on three orthogonal axes, declared in its hello’s propensity. They decide which chi it can keep.

The first axis is statefulness. A stateful bee holds its own session graph. A convention-stateful bee keeps no server state but speaks a protocol that implies continuation. A stateless bee treats each call as a fresh sid. A transport-only bee is pure bytes in and bytes out.

The second axis is richness. A rich bee hands humd cwd, permissions, MCP configs, and prior petals. A medium bee hands tools, system, and content. A lean bee hands only content and system. An opaque bee passes JSON straight through.

The third axis is wire, the outside contract the bee translates to, for example openai/chat, twilio/sms, x402/tool-call, or grpc/bidi.

A forager picks a contract that already exists in the wild and hides the rest of thrum behind it. A lean bee drops the tones it cannot express, while a rich one forwards everything.

Build a hive

1. Speak thrum

Connect to the humd socket at $XDG_RUNTIME_DIR/hum/thrum.sock, with the env override HUM_THRUM_SOCK, and exchange newline-delimited JSON tones. The reference clients are about ninety lines each. In Rust, nest_common::serve_worker and serve_forager run the whole loop for you, covering hello, prompt dispatch, chunk fan-out, and reconnect, so you implement one trait method and ship a main.rs. In TypeScript, Python, and Go, copy any of thrum-clients/ts, thrum-clients/python, or thrum-clients/go. humd does not care what language the process is written in.

2. Handshake, the hello contract

On connect, send chi:"hello" with these fields.

fieldmeaning
beerole array: ["worker"], ["forager"], or both
hiveyour kind name, for example "openai-server"
hidstable key-derived identity, described below, and mandatory
modelsmodel ids a worker serves; foragers may omit it
toolstool defs a forager exposes, each {name, description, inputSchema}
providescapability tags such as ["fs"] or ["session"]
version, protoVersionyour release, and the THRUM_VERSION you target
chisthe chi values you speak; advisory
sourceURL to your hive’s repo; informational, for humans only

The hid is mandatory and must be a real, stable Hid

The format is fbee_<hex> for a forager or wbee_<hex> for a worker, where the hex is sha256(ed25519 public key) derived from a persisted key. It must never be an invented string. The thrum client_id is per-connection and changes on every reconnect, so humd dedupes a bee across reconnects by its hid.

If the hid is missing, or if it does not parse as a canonical Hid, humd cannot dedupe and every reconnect leaks a fresh manifest. Your tool count then multiplies, growing by the number of tools on every reconnect, until humd restarts. humd warns about this with bee.hid.missing and bee.hid.invalid, and it also prunes a bee’s manifest on disconnect, but a valid hid is still required for correct identity.

Persist the key at $XDG_STATE_HOME/hum/bees/<kind>.key as a raw 32-byte ed25519 seed and reuse it on every boot. The reference implementations all produce a byte-identical hid. In Rust use nest_common::load_or_mint_bee_key from common. In TypeScript see hives/openai-server/src/identity.ts. In Go see beeHid in hives/twilio-sms/main.go.

Once the hello is accepted you are registered, and nothing else is required for single-machine use.

3. Translate, or transport

A forager maps incoming tones into its outside contract and back, as in vercel-ai/src/transform.ts. A transport simply forwards bytes, as in grpc. A worker turns chi:"prompt" into chunk and finish from whatever produces its tokens.

4. Tools

Forward each incoming chi:"tool-call" to your tool surface, then reply with chi:"tool-result" carrying the same callId, and humd resumes the parked model. humd already suppresses built-in tools that overlap a capability you list in provides, and an asker can also pass disallowedTools on the prompt.

chi cheatsheet

thrum-clients/ts/chi.ts owns the full registry (the Rust enum at thrum-core/src/chi.rs is the source of truth; codegen emits the rest). Most bees pick a subset.

subsetchi values
inference onlyprompt, chunk, finish, error, cancel
plus toolstool-call, tool-result
plus permissionspermission-ask, release-permit
plus state synchello, breath, session-ready, pulse, cleanup
plus observabilityperf-mark, drone, echo, log

A lean bee drops the tones it cannot express, while a rich one forwards everything and leans on consumer-side machinery to make sense of it.

Run a hive

There are three deployment shapes, and the protocol is identical across all of them.

In local dev you run cargo run -p humd and then launch your bee binary. Both sides resolve the same socket path, so there is no install and no service.

In the ensemble, a bee on one machine reaches a humd on another over the ensemble transport. The remote humd sees the same hello and routes normally. A peers.json with one bootstrap entry turns this on. Nothing installs on the remote humd’s disk, and the source URL stays purely informational.

As a managed service you keep a bee alive across reboots. Ship an Orchfile at your hive root declaring the SERVICE + RUN + RESTART (see any bundled hive for a template). hum hive install <target> resolves the target, builds the binary (Cargo / pnpm / Go / build script — detected from the marker file present), copies the Orchfile into ~/.config/hum/orch.d/, and asks orchd to bring the bee up as a user systemd unit (Linux) or launchd agent (macOS). orchd is the supervisor; from there the CLI drives it.

hum hive --list # catalogue: installer, configured, running
hum hive <name|path|url> install # build a hive and register its bee
hum bee --list # every bee with hid, role, models, tools, source, state
hum bee <name|id> enter # start a stopped bee
hum bee <name|id> exit # stop it, preserving state
hum bee <name|id> reenter # graceful restart with the same identity

hum bee reenter is the supported replacement for pkill, because it restarts through orchd and the bee keeps its persisted identity. hum hive install accepts the same dialect a bee advertises in its source: a bundled name, a local path, or a github.com/<org>/<repo>/tree/<branch>/<path> URL. Our own repo resolves to the local checkout, and a foreign one is shallow-cloned. The target must contain an Orchfile.

Discovery, optional

For mesh discovery, the ensemble gossips your manifest on hum/hives/announce, and peer humds find you through ensemble.hive_discover("<kind>"). See ensemble/README.md. For a censorship-resistant alternative to gossip, publish your manifest hash to a HumdRegistry, as described in contracts/. Both are opt-in, and a solo humd needs neither.

Versioning

THRUM_VERSION is defined in thrum-core/src/lib.rs (the Rust source of truth) and propagates verbatim through thrum-clients/{ts,python,go}/chi.* via codegen on every cargo build. It is independent of any package version. A patch covers additive optional fields. A minor covers a new chi value or a new field that has a backward-compatible path. A major covers a removed or renamed chi, or changed semantics. Each bee pins the version it targets, and humd traces every mismatch.

See also

  • nest/ defines WorkerBee, Cell, SpawnSpec, and the encoders. Process lifecycle (supervise, tree-kill, reap) lives in nest::lifecycle.
  • WIRE.md explains what the wire sees of nests and cells.
  • VOCABULARY holds the canonical entries for nest, hive, bee, worker, forager, nestler, and nestled.