Building Custom AI Skills with InstructLab Taxonomy
Create domain-specific AI capabilities using InstructLab's taxonomy system—from writing skill definitions to generating synthetic training data and validating fine-tuned models.
When you run docker compose up -d, the OpenClaw gateway container starts — but it’s not immediately ready to serve requests. There’s a startup window (typically 8–12 seconds) during which the gateway initializes its subsystems, loads hooks, and connects to external providers.
During this window, any requests to the gateway will fail:
$ curl -I http://127.0.0.1:18789
curl: (56) Recv failure: Connection reset by peerThis isn’t a crash. It’s the gateway booting up. Understanding this timing is critical for building reliable health checks and avoiding false positives in monitoring.
Based on real-world observation of OpenClaw v2026.2.25 startup logs, the gateway goes through these phases:
Docker starts the container, docker-init spawns the gateway process:
$ docker exec openclaw-openclaw-gateway-1 ps aux
PID USER COMMAND
1 node /sbin/docker-init -- docker-entrypoint.sh openclaw-gateway
7 node openclaw-gatewayThe gateway process (PID 7) begins loading the Node.js runtime and parsing configuration.
The gateway binds to the configured address and port:
[gateway] listening on ws://0.0.0.0:18789 (PID 7)Important: Just because the port is bound doesn’t mean the gateway is ready. The WebSocket server is listening, but hook loading hasn’t completed yet.
OpenClaw loads its hook system — the middleware pipeline that processes messages:
[gateway] hooks/
[gateway] ├─ health-monitor
[gateway] ├─ heartbeat
[gateway] ├─ canvas-mount
[gateway] ├─ browser
[gateway] └─ serverEach hook initializes in sequence. The hooks include:
| Hook | Purpose |
|---|---|
health-monitor | Internal health tracking |
heartbeat | Keep-alive mechanism |
canvas-mount | UI canvas framework |
browser | Browser-based interactions |
server | HTTP/WS server endpoints |
Channel providers connect to their external services:
[discord] [default] starting provider (@openclaw)
[discord] [default] logged in as MyBot#1234This is where fatal errors typically occur (e.g., Discord Error 4014). If a provider fails to connect and the error is fatal, the gateway crashes and restarts.
Once all hooks and providers complete initialization, the gateway is fully operational:
$ curl -I http://127.0.0.1:18789
HTTP/1.1 200 OKReal-world measurements from an Azure Standard B2s VM (2 vCPU, 4 GiB RAM):
| Phase | Time from start | Duration |
|---|---|---|
| Container init | 0s | ~1-2s |
| Port binding | ~2s | ~1s |
| Hook loading | ~3s | ~3-4s |
| Provider init | ~6s | ~2-4s |
| Fully ready | ~8-12s | — |
These timings vary based on:
Add a health check to your docker-compose.yml (or override file):
services:
openclaw-gateway:
# ... existing config ...
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:18789"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15sKey parameters:
start_period: 15s — Grace period before health checks begin. Set this to be longer than your typical startup time.interval: 10s — Time between health checks after the start period.retries: 5 — Number of consecutive failures before marking unhealthy.$ docker inspect --format='{{.State.Health.Status}}' \
openclaw-openclaw-gateway-1
healthyPossible statuses:
starting — Within the start_periodhealthy — Last health check passedunhealthy — Consecutive failures exceeded retriesIf you have scripts that need to wait for the gateway to be ready:
#!/bin/bash
# wait-for-gateway.sh
MAX_WAIT=30
INTERVAL=2
ELAPSED=0
echo "Waiting for OpenClaw gateway..."
while [ $ELAPSED -lt $MAX_WAIT ]; do
if curl -sf http://127.0.0.1:18789 > /dev/null 2>&1; then
echo "Gateway is ready! (${ELAPSED}s)"
exit 0
fi
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done
echo "Gateway failed to start within ${MAX_WAIT}s"
exit 1docker compose logs -f openclaw-gatewayWatch for the “listening on” message followed by provider login confirmation.
watch -n 1 'docker compose ps && echo "---" && \
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
http://127.0.0.1:18789 2>/dev/null || echo "Not ready"'This refreshes every second, showing you both the container status and HTTP readiness.
# Record start time
START=$(date +%s)
docker compose up -d
# Poll until ready
while ! curl -sf http://127.0.0.1:18789 > /dev/null 2>&1; do
sleep 1
done
END=$(date +%s)
echo "Ready in $((END - START)) seconds"The symptoms look identical — both show connection resets. Here’s how to tell them apart:
| Indicator | Normal Startup | Crash-Restart Loop |
|---|---|---|
| Duration | 8-12 seconds | Repeats indefinitely |
docker compose ps uptime | Increases steadily | Resets periodically |
| Logs after 30s | Show “listening on” | Show fatal error or empty |
| curl after 30s | Returns 200 | Still returns connection reset |
The 30-second test: If curl still returns “Connection reset by peer” after 30 seconds, it’s a crash loop, not a slow startup.
docker compose pullPulling the image before starting avoids the large download during the first startup.
If you only need the API gateway (no Discord, no other channels), disable unused providers:
docker compose run --rm openclaw-cli config set \
channels.discord.enabled falseFewer providers = faster startup.
On an Azure B1s (1 vCPU, 1 GiB), startup can take 20+ seconds. Upgrading to a B2s (2 vCPU, 4 GiB) cuts it roughly in half.
Docker Compose v2 supports the --wait flag that blocks until health checks pass:
docker compose up -d --waitThis requires a healthcheck configured in docker-compose.yml.
Before considering your OpenClaw deployment production-ready, verify:
docker-compose.ymlstart_period set to at least 15s (or your observed max startup time + buffer)AI & Cloud Advisor with 18+ years experience. Author of 8 technical books, creator of Ansible Pilot. Speaker at KubeCon EU & Red Hat Summit 2026.
Create domain-specific AI capabilities using InstructLab's taxonomy system—from writing skill definitions to generating synthetic training data and validating fine-tuned models.
How to access the OpenClaw Control UI dashboard from an Azure VM — via SSH tunnel (secure) or public IP. Covers device pairing, dashboard authentication, and the browser-based management interface.
End-to-end guide to building a complete persistent memory system for your OpenClaw AI agent. Combine memory flush, hybrid search, file-backed notes, SQLite indexing, and session hooks into a cohesive knowledge architecture.