Gateway Restart Continuation
Use when a task requires openclaw gateway restart, openclaw daemon restart, or another OpenClaw Gateway restart/reload that may interrupt the active chat. Also use after restart if a continuation file exists or the chat reports a Gateway/app-server disconnect.
Safety Boundary
- Treat Gateway restart as a shared-system interruption. A forced Gateway restart can interrupt other agents, active turns, background tasks, cron jobs, tool calls, and channel delivery.
- Do not restart Gateway from chat unless the user explicitly requested or approved that exact restart.
- Before scheduling a restart, inspect active OpenClaw agents, sessions, tasks, and scheduler state when tools/CLI are available.
- If other agents, active sessions, queued/running tasks, active cron work, or inconclusive checks appear, do not restart automatically. Wait or ask unless the user explicitly approves interrupting other work.
- The active assistant turn must end before the Gateway restart happens.
- Recovery must be actively scheduled before the restart; do not assume a skill will run by itself after Gateway comes back.
- Use an external detached executor for restart and recovery. The known-good shape is a
systemd-run --userwrapper that sleeps briefly, restarts Gateway, waits for health OK, then delivers a recovery message into the saved session. - Do not use OpenClaw cron as the primary recovery wake for this workflow unless the exact restart timing has been tested. A cron wake scheduled before a delayed restart can fire too early and be interrupted by the later restart.
- Never store secrets, tokens, passwords, approval links, or private command output in the continuation file.
Paths
Use portable workspace paths:
WORKSPACE="${OPENCLAW_WORKSPACE:-$HOME/.openclaw/workspace}"
STATE="$WORKSPACE/state/gateway-restart-continuation.md"
LOG="/tmp/openclaw-gateway-restart/restart.log"
HEALTH_LOG="/tmp/openclaw-gateway-restart/health.log"
Create $(dirname "$STATE") before writing the continuation file.
Runtime Values
Derive these when scheduling the restart:
Created: current runtime date, time, and timezone, for exampledate '+%Y-%m-%d %H:%M %Z'.Recovery session key: exactSession:value fromsession_status(current).Recovery route: current route context, provider-neutral: Discord, Slack, Telegram, WhatsApp, terminal, etc.Safety check: summarize agents/sessions/tasks/cron checked and whether safe, blocked, or user-overridden.Recovery unit: transient systemd unit name used for restart/recovery.
Never reuse example session keys or route values.
Shared-System Safety Check
Prefer runtime tools when available:
session_status(current)for the current session and queue state.subagentsor equivalent session tooling for active/recent subagents.cron statusandcron listfor scheduler state.- Task/goal/session tools if exposed by the runtime.
When using the OpenClaw CLI, use read-only/status commands:
openclaw agents list --json
openclaw sessions --all-agents --active 15 --json
openclaw tasks list --status running --json
openclaw tasks list --status queued --json
openclaw cron status --json
Interpret conservatively:
- Safe: no queued/running tasks, no obvious active cron work, and no active/recent sessions except the current restart-requesting session.
- Probably unsafe: any other agent has an active/recent session, any task is queued/running, cron reports active work, or checks fail in a way that prevents confidence.
- Explicit override: the user specifically says to restart now, restart anyway, interrupt other agents/tasks, or otherwise acknowledges the risk.
If probably unsafe and no explicit override:
- Do not schedule the restart.
- Tell the user what is active or what could not be checked.
- Offer to wait, retry checks later, or proceed only if they explicitly approve interrupting work.
- Keep any existing continuation file intact, but do not claim automatic recovery was scheduled.
Continuation File
Use $STATE, normally $OPENCLAW_WORKSPACE/state/gateway-restart-continuation.md, falling back to $HOME/.openclaw/workspace/state/gateway-restart-continuation.md.
Keep it short and actionable:
# Gateway Restart Continuation
Created: <runtime date/time/timezone>
Reason: <why the restart is needed>
Restart command: `<exact command>`
Scheduled restart command: `<external detached restart/recovery command>`
Recovery unit: `<transient systemd unit name>`
Recovery session key: `<exact current Session value from session_status(current)>`
Recovery route: `<current route context: provider/channel/target/accountId when available>`
Safety check: `<agents/sessions/tasks/cron checked; safe, blocked, or user override>`
## Continue
I am continuing: <task name>
## Current State
- <what was already done>
- <what still needs verification>
## Next Steps
1. <first action after restart>
2. <second action>
3. <finish/cleanup condition>
## Cleanup
Clear this file after the task is fully complete.
Restart And Recovery Executor
Use a health-gated systemd wrapper outside the active assistant turn. It restarts Gateway, waits for openclaw gateway health, then delivers a recovery turn.
Template:
WORKSPACE="${OPENCLAW_WORKSPACE:-$HOME/.openclaw/workspace}"
STATE="$WORKSPACE/state/gateway-restart-continuation.md"
LOG="/tmp/openclaw-gateway-restart/restart.log"
HEALTH_LOG="/tmp/openclaw-gateway-restart/health.log"
SESSION_KEY="<exact current Session value from session_status(current)>"
UNIT="openclaw-gateway-restart-recover-$(date +%s)"
mkdir -p "$(dirname "$STATE")" /tmp/openclaw-gateway-restart
systemd-run --user --unit="$UNIT" /bin/bash -lc '
set -u
STATE="$1"
LOG="$2"
HEALTH_LOG="$3"
SESSION_KEY="$4"
mkdir -p "$(dirname "$LOG")"
{
echo "[$(date -Is)] Waiting before Gateway restart"
sleep 5
echo "[$(date -Is)] Restarting Gateway"
openclaw gateway restart --force
echo "[$(date -Is)] Waiting for Gateway health"
ok=0
for i in $(seq 1 60); do
if openclaw gateway health >"$HEALTH_LOG" 2>&1; then
ok=1
break
fi
sleep 1
done
if [ "$ok" -ne 1 ]; then
echo "[$(date -Is)] Gateway health did not recover"
exit 1
fi
echo "[$(date -Is)] Gateway healthy; delivering recovery turn"
openclaw agent \
--session-key "$SESSION_KEY" \
--message "Gateway restart recovery: read $STATE first, announce what you are continuing, complete the saved next steps, then clear the continuation file when done." \
--deliver
deliver_rc=$?
if [ "$deliver_rc" -ne 0 ]; then
if tail -n 80 "$LOG" 2>/dev/null | grep -Fq "Already compacted"; then
echo "[$(date -Is)] Recovery delivery returned $deliver_rc after transcript was already compacted; treating as post-delivery non-fatal"
else
echo "[$(date -Is)] Recovery delivery failed with exit code $deliver_rc"
exit "$deliver_rc"
fi
fi
} >>"$LOG" 2>&1
' bash "$STATE" "$LOG" "$HEALTH_LOG" "$SESSION_KEY"
Notes:
- The wrapper must wait for
openclaw gateway healthbefore delivering recovery. openclaw agent --delivercan sometimes deliver the recovery turn and then exit nonzero withGatewayClientRequestError: CLI transcript compaction failed ... Already compacted. Treat that exact post-delivery compaction case as non-fatal so the transient unit does not end failed.- Do not ignore other
openclaw agent --deliverfailures. Log them and exit nonzero. - The transient unit may be
active runningwhile the delivered recovery turn is still executing. After the recovery turn finishes, the unit should exit and disappear. - If
systemd-run --useris unavailable, use another approved external scheduler that survives Gateway restart and runs the same health-gated recovery logic. If none exists, do not claim automatic recovery is available.
Before Restart
- Inspect enough state to know what remains.
- Run the shared-system safety check. Stop if unsafe/inconclusive unless the user explicitly approved interrupting work.
- Identify the recovery target.
- Prefer
session_status(current). - Copy the exact
Session:value as the recovery session key. - Copy route context as provider-neutral audit/fallback details.
- If no reliable session key or reply target is known, say automatic recovery cannot be guaranteed and keep the continuation file intact.
- Prefer
- Resolve
WORKSPACE,STATE,LOG, andHEALTH_LOG; create$(dirname "$STATE"). - Capture runtime timestamp with timezone.
- Write the continuation file with reason, exact restart command, scheduled restart/recovery command, recovery unit, session key, route context, safety result, current state, and next steps.
- Schedule the detached health-gated restart/recovery wrapper.
- After scheduling returns, do not run more tools in that turn. Tell the user:
I wrote the continuation note and scheduled the health-gated Gateway restart/recovery. Unit: <unit>. I am ending this turn now so the restart will not cut me off. After Gateway comes back healthy, I should automatically continue: <task>.
- End the turn before restart happens.
After Restart / Recovery
When the delivered recovery turn starts, or when a user message arrives after restart, check the continuation file first.
If $STATE exists and has content:
- Read
$STATEbefore doing interrupted-task work. - Announce what is being continued.
- Complete saved next steps.
- Verify Gateway health and task outcome.
- Confirm no transient restart/recovery unit remains loaded. If it is still active only because it is waiting for the current delivered recovery turn, say so and check again after the turn if needed.
- When the task is complete, remove only
$STATEor replace it with an empty file. - Tell the user the task is done and the continuation note was cleared.
If $STATE is missing, empty, or stale:
- Say no restart continuation note was available.
- Reconstruct from recent chat/tool state if possible.
- Ask the user only if the next safe step cannot be recovered.
Failure Handling
If wrapper scheduling fails:
- Keep the continuation file intact.
- Report the failure and next safest option.
- Do not schedule restart unless the user accepts manual recovery.
If Gateway health fails in the wrapper:
- Leave the continuation file intact.
- Inspect
/tmp/openclaw-gateway-restart/restart.logand/tmp/openclaw-gateway-restart/health.lognext turn. - Do not repeatedly restart in a loop.
If the transient unit remains failed:
- Inspect its status and
/tmp/openclaw-gateway-restart/restart.log. - If the only failure is the exact post-delivery
Already compactedcompaction case and recovery did arrive, record that as a wrapper bug and clear the failed unit state withsystemctl --user reset-failed <unit>after verification. - Otherwise, treat it as a real recovery failure and keep the continuation file until the task is resolved or abandoned.
