How it works
Every Buttress server runs a UDP transport on port8089:
- ANNOUNCE — broadcast every 5 seconds with the server’s
serverInfo(capabilities, generators, auth status). - QUERY — a launcher can broadcast a query and the server unicasts a RESPONSE back. Response delays are randomized to avoid storms when many servers reply at once.
0.0.0.0:8089 for incoming queries, and one send socket per local broadcast interface so each subnet broadcast leaves on the right NIC.
Announcement payload
serverInfo includes a generators[] array with per-backend hardware capabilities computed once at startup:
ggml-llm as well — its embedding and tokenizer contexts run on the LLM backend — so any server announcing that type is a candidate.
functions appears only on servers with local functions enabled, and carries presence and count only — never the tool list, which would not fit in a UDP datagram.
Capability score
The score is a 0-100 number combining:
A laptop with no GPU scores around 15-25; a workstation with an RTX 4090 lands near 80-90.
Trust model
Bound servers and unbound servers both announce, but launchers treat them differently:- Unbound servers (
authentication.required = false) appear as untrusted endpoints. They are still usable from manual / public clients, but bound launchers ignore them. - Bound servers (
authentication.required = true) are trusted only when theirserverIdis in the workspace’s bound-server list and the announcement is signed by the matching per-server announce key the workspace registered at bind time.
Signed announcements
Each Buttress server has its own Ed25519 announce keypair, generated bybricks buttress bind. The public half is registered with the BRICKS cloud and surfaced to launchers via myWorkspaceButtress.buttressServers[].serverPublicKey; the private half stays in ~/.bricks-cli/buttress/state.json on the server host.
Every UDP ANNOUNCE and RESPONSE from a bound server carries a signature over { t, d, ts }. Launchers verify the signature against the registered key with a 30-second replay window — packets without a valid signature never enter the endpoint pool. This closes the spoof vector where a LAN peer could re-announce a bound serverId and try to receive a workspace bearer token.
The wire protocol version bumped to 2.0 for signed traffic. Launchers and servers running protocol 1.0 silently drop 2.0 packets and vice versa, so old/new combinations co-exist by going dark rather than swapping unsigned trust. To upgrade an existing bound server, re-run bricks buttress bind (which mints a new announce keypair) and restart bricks-buttress.
Manual override
When auto-discovery is impractical (devices on a different subnet, or a cloud-hosted Buttress server), each LLM/STT brick in BRICKS Controller’s Config Editor lets you switch from Auto to Manual and type the WebSocket URL directly. See Use Buttress from Foundation.HTTP fallback
A launcher can also query a known IP directly over HTTP:serverInfo payload as the UDP ANNOUNCE. Foundation launchers use this path internally when UDP broadcast is blocked (some enterprise Wi-Fi networks).
Troubleshooting
Next steps
Workspace binding
How a server’s
kid and bound-server list are issued.Use from Foundation
Per-brick connection settings: Auto vs Manual, strategy, fallback.