# PRD: OpenClaw Local Model Cost Control (Setup Max) ## 1) Document Purpose Define requirements for a reusable OpenClaw setup that supports: - Instant manual switching between paid and free model profiles - Optional scheduled switching (day/night) - Optional budget protection for expensive models Audience: - Primary: local operator (non-expert friendly) - Secondary: future maintainer cloning this setup for another machine ## 2) Problem Statement Running a paid model 24/7 can create unnecessary spend. Operators need an easy way to: - Switch to free local models on demand - Automate free mode during off-hours - Prevent accidental long-running use of expensive models ## 3) Goals - G1: One-command live switch between `paid` and `free` profiles. - G2: Support day/night automatic profile switching. - G3: Provide guardrail warning + optional auto-revert from high-cost model usage. - G4: Make setup operable by a newbie using copy/paste commands. ## 4) Non-Goals - Building a new OpenClaw provider plugin. - Replacing OpenClaw internal routing. - Managing billing dashboards directly. ## 5) User Stories - As an operator, I can run one command to switch to free local models immediately. - As an operator, I can switch back to paid model for deep tasks. - As an operator, I can set free mode from 10pm-7am automatically. - As an operator, I get warned if expensive model remains active too long. - As a maintainer, I can copy this folder to another Mac and follow docs to bootstrap. ## 6) Functional Requirements ### FR-1 Profile Configuration - System must define named model profiles in JSON: - `paid` - `free` - Each profile must include: - `primary` model - ordered fallback list Implementation: - `config/model-profiles.config.json` ### FR-2 Manual Live Switch - Must support: - `model_profile_switch.sh paid` - `model_profile_switch.sh free` - Must: - update OpenClaw primary model - reset + apply fallback list - optionally push `/model ` to active session key - Must support flags: - `--no-live` - `--no-status` - `status` Implementation: - `scripts/model_profile_switch.sh` ### FR-3 Schedule Guard - Must read schedule config and apply profile by hour. - Must support day and night windows. - Must run idempotently and avoid unnecessary switches. - Must correct drift if current default model does not match expected scheduled profile. Implementation: - `config/model-schedule.config.json` - `scripts/model_schedule_guard.sh` - `scripts/install_model_schedule_guard_launchd.sh` ### FR-4 Budget Guard - Must detect if active session model is in high-cost allowlist. - Must warn after configurable threshold. - Must auto-revert after configurable threshold. - Must throttle warnings/reverts to avoid spam loops. Implementation: - `config/model-budget-guard.config.json` - `scripts/model_budget_guard.sh` - `scripts/install_model_budget_guard_launchd.sh` ### FR-5 Install Convenience - Must provide one script to install both schedule and budget guards. Implementation: - `scripts/install_local_model_guardrails.sh` ### FR-6 Documentation - Must include a step-by-step README for first-time users. - Must include verification commands and disable/uninstall steps. Implementation: - `README.md` ### FR-7 Existing-Install Upgrade Workflow - Must provide one command for in-place upgrades on existing machines. - Must back up OpenClaw config/session files before migration/update. - Must run config migration (`openclaw doctor --fix`) before attempting update. - Must update CLI using built-in updater with timeout + npm fallback. - Must emit timestamped update logs for operator traceability. - Must stop gateway before update and bring gateway back after update. - Must ensure gateway LaunchAgent is loaded/running after update. - If `~/.openclaw` is symlinked to `/Volumes/...`, must ensure gateway LaunchAgent logs use `/tmp/openclaw-gateway.launchd*.log` to avoid launchd `EX_CONFIG`. - Must reinstall and kickstart budget/schedule guard LaunchAgents after update. Implementation: - `scripts/update_openclaw.sh` - `setup/setup_openclaw_ollama.sh` ## 7) Non-Functional Requirements - NFR-1 Reliability: scripts should be safe to run repeatedly. - NFR-2 Observability: each LaunchAgent writes stdout/stderr logs to `/tmp`. - NFR-3 Compatibility: target macOS + zsh/bash + OpenClaw CLI. - NFR-4 Safety: avoid exposing secrets in script output. - NFR-5 Usability: all common actions available as copy/paste commands. ## 8) Architecture Overview Inputs: - OpenClaw session state (`~/.openclaw/agents/main/sessions/sessions.json`) - Profile/schedule/budget JSON configs Executors: - Manual CLI script (`model_profile_switch.sh`) - Launchd workers (`model_schedule_guard.sh`, `model_budget_guard.sh`) Outputs: - Updated OpenClaw model + fallbacks in config - Optional live `/model` message into active session - Log files in `/tmp` ## 9) Operational Flow ### Flow A: Manual Switch 1. Operator runs switch command. 2. Script loads profile from config. 3. Script applies primary + fallbacks. 4. Script pushes live model command to active session (unless `--no-live`). 5. Script prints status. ### Flow B: Scheduled Switch 1. LaunchAgent triggers every 5 minutes. 2. Guard computes desired profile from local hour. 3. Guard checks last applied profile + current default model. 4. If mismatch, applies desired profile. 5. Guard stores state timestamp. ### Flow C: Budget Protection 1. LaunchAgent triggers every 2 minutes. 2. Guard inspects active session model. 3. If model is high-cost: - warn after threshold - auto-revert after threshold 4. Guard updates state file for rate-limiting. ## 10) Acceptance Criteria - AC-1: Running `bash ./scripts/model_profile_switch.sh free` changes default to `openrouter/qwen/qwen3-coder:free`. - AC-2: Running `bash ./scripts/model_profile_switch.sh paid` restores default to `openrouter/moonshotai/kimi-k2.5`. - AC-3: With schedule enabled (`22`/`7`), profile changes correctly by local time window. - AC-4: If operator manually drifts model during scheduled window, schedule guard re-aligns on next run. - AC-5: Budget guard warns and reverts when high model remains active beyond thresholds. - AC-6: New operator can follow README from zero knowledge and complete setup without editing scripts. - AC-7: Running `bash ./scripts/update_openclaw.sh` upgrades an existing install and prints a healthy gateway/model status at completion. - AC-8: After update, schedule + budget LaunchAgents are loaded and can run immediately when kickstarted. - AC-9: Upgrade output lines include timestamps to support restart/audit troubleshooting. ## 11) Risks and Mitigations - Risk: model names differ across machines. - Mitigation: update `config/model-profiles.config.json` per machine. - Risk: LaunchAgents not loaded after reboot/login changes. - Mitigation: include explicit `launchctl print` checks and reinstall command. - Risk: missing CLI dependencies (`jq`, `openclaw`). - Mitigation: prerequisite checks in README. - Risk: user confusion between ChatGPT subscription and API billing. - Mitigation: clear FAQ note in README. - Risk: gateway LaunchAgent exits with `EX_CONFIG` when logs point into external-volume symlink paths. - Mitigation: force gateway LaunchAgent stdout/stderr to `/tmp/openclaw-gateway.launchd*.log` when `~/.openclaw` resolves to `/Volumes/...`. ## 12) Rollout Plan 1. Validate scripts (`bash -n` and status commands). 2. Perform manual switch tests (`free` then `paid`). 3. Enable schedule (`enabled=true`) and install schedule LaunchAgent. 4. Install budget LaunchAgent. 5. Monitor logs for one day. 6. Clone/copy to future machine and adjust profile model IDs as needed. ## 13) Future Enhancements - Optional quiet-hours policy to disable non-essential notifications. - Per-channel session key mapping (Telegram/Discord-specific switching). - Daily spend estimator from model usage telemetry. - Optional provider locking profile policies.