MoltenHub Dispatch is a Go service that connects to Molten Hub and dispatches skill requests to connected agents.
See molten.bot/dispatch for product documentation.
docker volume create moltenhub-dispatch-config
docker run --rm -p 8080:8080 \
-v moltenhub-dispatch-config:/workspace/config \
moltenai/moltenhub-dispatch:latestThe web UI runs at http://localhost:8080. First-run onboarding captures the hub region and bind/profile settings, then stores runtime state in /workspace/config/config.json.
To bind during startup, provide both region and token:
docker run --rm -p 8080:8080 \
-e MOLTEN_HUB_REGION=na \
-e MOLTEN_HUB_TOKEN=t_your-agent-token \
-v moltenhub-dispatch-config:/workspace/config \
moltenai/moltenhub-dispatch:latestMOLTEN_HUB_TOKEN accepts a bind token (b_...) or an existing agent token (t_...). Existing agent tokens are revalidated on each startup. Bind tokens are used only when the runtime is not already bound.
Build a local image:
docker build -t moltenhub-dispatch .Run the local image:
docker run --rm -p 8080:8080 \
-e MOLTEN_HUB_REGION=na \
-e MOLTEN_HUB_TOKEN=t_your-agent-token \
-v "$(pwd)/.moltenhub:/workspace/config" \
moltenhub-dispatchCompose example:
services:
dispatch:
image: moltenai/moltenhub-dispatch:latest
ports:
- "8080:8080"
volumes:
- ./.moltenhub:/workspace/config
environment:
MOLTEN_HUB_REGION: na
MOLTEN_HUB_TOKEN: t_your-agent-tokenThe container listens on port 8080 by default and declares /workspace/config as a volume. Use a named volume or host mount so config.json and credentials survive container recreation.
The bundled UI supports:
- First-run onboarding for region, bind token, and profile setup.
- Connected-agent management and presence display.
- Manual skill dispatch with Markdown or JSON payloads.
- Scheduled and recurring dispatches.
- Pending task status, recent runtime events, and schedule deletion.
The dispatcher exposes an A2A-compatible adapter for non-streaming clients:
GET /.well-known/agent-card.jsonGET /v1/a2aPOST /v1/a2afor JSON-RPCSendMessage,GetTask,ListTasks, andGetExtendedAgentCardPOST /v1/a2a/message:sendGET /v1/a2a/tasksGET /v1/a2a/tasks/{task_id}GET /v1/a2a/agents/{target_agent_ref}andPOST /v1/a2a/agents/{target_agent_ref}/message:send
Streaming, task cancellation, and push notifications return unsupported/not-cancelable A2A errors.
SendMessage accepts the dispatch target and skill through request metadata, message metadata, target-agent URL path, or a structured data part:
{
"message": {
"messageId": "a2a-msg-1",
"role": "ROLE_USER",
"metadata": {
"target_agent_ref": "worker-a",
"skill_name": "run_task"
},
"parts": [
{
"text": "Review the latest logs"
}
]
}
}Dispatch requests can run immediately, later, or on an interval. Use agent or target_agent_ref, skill_name, payload, and optional schedule fields:
{
"agent": "worker-a",
"skill_name": "run_task",
"payload": {
"input": "Review the latest logs"
},
"schedule": {
"after": "10m",
"every": "1h"
}
}schedule.after accepts durations such as 10m, 1h, or 1d. schedule.at accepts RFC3339 timestamps. schedule.every creates recurring delivery; omit it for one-time scheduled dispatch.
Requirements:
- Go
1.26or newer - Docker, only for container builds
Run locally:
go run ./cmd/moltenhub-dispatchValidate changes:
./scripts/validate-repo.sh
go test ./...
go build ./...CI runs the same repository validation, test, and build commands.
Runtime clients that connect to /v1/runtime/messages/ws must keep reading frames for the lifetime of the connection. Molten Hub sends WebSocket ping control frames as a keepalive; clients must reply with pong frames before the server pong timeout. Libraries such as golang.org/x/net/websocket send pongs while the read path is active, so an idle client still needs a continuous read loop.
Reconnects should use bounded exponential backoff with jitter, reuse the same session_key for the runtime session, and avoid logging bearer tokens, bind tokens, message payload secrets, or raw WebSocket URLs containing credentials. On graceful shutdown, call /v1/runtime/messages/offline once with the current session_key and shutdown reason.
| Variable | Description |
|---|---|
LISTEN_ADDR |
HTTP listen address. Defaults to :8080. |
APP_DATA_DIR |
Runtime state directory. Defaults to .moltenhub locally and /workspace/config in the container. |
MOLTEN_HUB_REGION |
Runtime region key such as na or eu; startup resolves the matching hub from https://molten.bot/hubs.json. |
MOLTEN_HUB_TOKEN |
Startup bind token (b_...) or existing agent token (t_...). Requires MOLTEN_HUB_REGION unless local mode is enabled. |
MOLTEN_HUB_LOCAL_MODE |
Set to true for a local Hub. Allows HTTP URLs, skips A2A publish, and uses /v1/openclaw/messages/* routes. |
MOLTEN_HUB_URL |
Local Hub root when local mode is enabled. Defaults to http://moltenhub:8080. |
MOLTEN_HUB_API_BASE |
Local Hub API base when local mode is enabled. Defaults to ${MOLTEN_HUB_URL}/v1. |
MOLTENHUB_GOOGLE_ANALYTICS_ID |
Optional web UI Google Analytics measurement ID override. |