← back to Ticket System
wire-openclaw-exo: wait for gateway 200 before cron edits (first run lost them at http 000)
e1ee158a2f7db8e75ec112ba240b398d8ef18bac · 2026-09-18 13:04:30 -0700 · Steve Abrams
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YT3be6iadPzjKJDiaTasEE
Files touched
A scripts/wire-openclaw-exo.sh
Diff
commit e1ee158a2f7db8e75ec112ba240b398d8ef18bac
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 18 13:04:30 2026 -0700
wire-openclaw-exo: wait for gateway 200 before cron edits (first run lost them at http 000)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YT3be6iadPzjKJDiaTasEE
---
scripts/wire-openclaw-exo.sh | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/scripts/wire-openclaw-exo.sh b/scripts/wire-openclaw-exo.sh
new file mode 100755
index 00000000..0e88648c
--- /dev/null
+++ b/scripts/wire-openclaw-exo.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+# wire-openclaw-exo.sh — point openclaw at the exo ring (Steve 2026-09-18: "no more ollama, use our own system").
+# Idempotent + reversible: backs up openclaw.json, ledgers every step. Usage: wire-openclaw-exo.sh <model_id> [ring_base]
+set -uo pipefail
+M="${1:?model id}"; BASE="${2:-http://127.0.0.1:52415/v1}"
+T=TK-11903-overnight-close-audit-2026-09-18-verify; export TK_AGENT=overnight-close-audit
+q(){ "$@" 2>&1 | grep -vE "Config warnings|plugins.entries|ignored; remove|^\s*$|^│|^◇|^├"; }
+LX=~/.claude/yolo-queue/executed-reversible/log-exec.mjs
+# 0. prove the ring answers THIS model before touching config
+out=$(curl -s -m 120 -X POST "$BASE/chat/completions" -H 'Content-Type: application/json' -d "{\"model\":\"$M\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly: EXO_OK\"}],\"max_tokens\":20}" | jq -r '.choices[0].message.content // ""'); case "$out" in *EXO_OK*) echo "ring answers: $out";; *) echo "ABORT: ring did not answer ($out)"; exit 1;; esac
+BK=~/.openclaw/openclaw.json.bak-exo-$(date +%Y%m%d-%H%M%S); cp ~/.openclaw/openclaw.json "$BK"
+# 1. provider + allowlist + primary
+q openclaw config set models.providers.exo "{\"baseUrl\":\"$BASE\",\"apiKey\":\"exo-local\",\"api\":\"openai-completions\",\"models\":[{\"id\":\"$M\",\"name\":\"exo ring $M\",\"input\":[\"text\"],\"cost\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0},\"contextWindow\":131072,\"maxTokens\":8192,\"reasoning\":false}]}" | tail -1
+q openclaw config set agents.defaults.models "{\"exo/$M\":{}}" | tail -1
+q openclaw config set agents.defaults.model.primary "exo/$M" | tail -1
+launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway
+# cron edits go THROUGH the gateway — wait until it answers (first run 2026-09-18 lost both edits at "http 000")
+for i in $(seq 1 30); do c=$(curl -s -m 3 -o /dev/null -w '%{http_code}' http://127.0.0.1:18789/); [ "$c" = 200 ] && break; sleep 2; done; echo "gateway http $c after ~$((i*2))s"; [ "$c" = 200 ] || { echo "ABORT: gateway never came back; config is set but cron jobs NOT touched"; exit 1; }
+# 2. night jobs -> ring model, enable
+for j in 914c00eb-78db-4b75-b130-d34d7410688f 5071d4c2-1520-43ec-a6e3-d517b9943b09; do q openclaw cron edit $j --model "exo/$M" >/dev/null; q openclaw cron enable $j >/dev/null; done
+jq -r '(.jobs[]? // .[]?) | select(.id|test("914c00eb|5071d4c2")) | "\(.id[0:8]) enabled=\(.enabled) model=\(.model // .payload.model // "?")"' ~/.openclaw/cron/jobs.json
+node $LX --agent overnight-close-audit --ticket $T --action "openclaw wired to exo ring: provider exo ($BASE), primary+allowlist exo/$M, night jobs 914c00eb+5071d4c2 on it and ENABLED" --blast-radius 3 --undo "cp $BK ~/.openclaw/openclaw.json; openclaw cron disable 914c00eb-78db-4b75-b130-d34d7410688f; openclaw cron disable 5071d4c2-1520-43ec-a6e3-d517b9943b09; launchctl kickstart -k gui/\$(id -u)/ai.openclaw.gateway" --verify "openclaw cron run 5071d4c2 -> status ok provider=exo" >/dev/null 2>&1
+tk log $T "openclaw wired to exo ring (exo/$M @ $BASE); backup $BK; night jobs enabled on it." >/dev/null
+# 3. live test
+fire=$(date +%s000); q openclaw cron run 5071d4c2-1520-43ec-a6e3-d517b9943b09 | grep runId; echo "fired $(date -u +%FT%TZ)"
+f=~/.openclaw/cron/runs/5071d4c2-1520-43ec-a6e3-d517b9943b09.jsonl
+until jq -e --argjson t $fire 'select(.runAtMs>=$t and (.status=="ok" or .status=="error"))' "$f" >/dev/null 2>&1; do sleep 10; done
+jq -r --argjson t $fire 'select(.runAtMs>=$t) | [(.runAtMs/1000|todate), .status, .provider, .model, (.durationMs|tostring), (.error//""|.[0:120])] | @tsv' "$f"
+sid=$(jq -r --argjson t $fire 'select(.runAtMs>=$t) | .sessionId' "$f" | tail -1); tf=~/.openclaw/agents/main/sessions/$sid.jsonl
+[ -f "$tf" ] && { echo "tool calls: $(grep -oE '"name":"[a-zA-Z_]+"' "$tf" | wc -l | tr -d ' ') by name: $(grep -oE '"name":"[a-zA-Z_]+"' "$tf" | sort | uniq -c | sort -rn | head -5 | tr '\n' ' ')"; echo "last assistant:"; grep -E '"role":"assistant"' "$tf" | tail -1 | jq -r '.message.content // .content | if type=="array" then map(.text // "")|join(" ") else . end' 2>/dev/null | head -c 500; echo; }
+echo "tk events by openclaw-night-* since fire: $(jq -r --arg s "$(date -u -r $((fire/1000)) +%FT%TZ)" 'select(.ts>=$s and ((.agent//"")|test("openclaw-night"))) | .ts' ~/.claude/tickets/events.jsonl | wc -l | tr -d ' ')"
← 427e7cc7 auto-data-snapshot: 2026-09-18T09:26:51 (1 data files) — dat
·
back to Ticket System
·
TK-11855: read-only PM2_HOME caller audit — precondition SAT 1cfdd01b →