$npx -y skills add Senpi-ai/senpi-skills --skill senpi-strategy-opsDeploy / monitor / close a NAMED Senpi trading strategy. Use when the user names a strategy to run — "install spider", "deploy polar", "set up kodiak", "run the spider strategy", "is my strategy live?", "what am I running", "list my strategies" (→ status.py), "are my positions pr
| 1 | # Senpi Strategy Ops — deploy, monitor, close |
| 2 | |
| 3 | A strategy is a **package**: `strategy.yaml` (the deploy manifest) + one `runtime.yaml` per instance + |
| 4 | `<instance>/scanners/`. The runtime **spawns and supervises** each `scanners/scan.py`, calling |
| 5 | `scan(inputs, ctx)` every `interval_seconds` and owning everything downstream — signal validation, |
| 6 | sizing/execution, the two-phase DSL exit, risk guard-rails. **There is no separate scanner daemon, no |
| 7 | `push_signal`.** Ops owns the deployed lifecycle. Deploy is **three short, resumable steps** (each fits a |
| 8 | tool call — wallet funding and the first scan tick are slow, so they must not block one long call): |
| 9 | |
| 10 | ``` |
| 11 | python3 senpi-strategy-ops/scripts/deploy.py validate <id> # 0. preflight — deploy-ready? (no side effects) |
| 12 | python3 senpi-strategy-ops/scripts/deploy.py create <id> --budget <usd> # 1. create wallets & fund them |
| 13 | python3 senpi-strategy-ops/scripts/deploy.py runtime <id> # 2. register the runtime(s) |
| 14 | python3 senpi-strategy-ops/scripts/deploy.py verify <id> # 3. GATE — confirm LIVE (runtime+scanner+DSL+budget) |
| 15 | python3 senpi-strategy-ops/scripts/status.py # what am I running? (+ health) |
| 16 | python3 senpi-strategy-ops/scripts/close.py <id> # teardown one strategy |
| 17 | python3 senpi-strategy-ops/scripts/close.py --all # teardown EVERY open strategy |
| 18 | ``` |
| 19 | **Always tear down through `close.py`** (one `<id>` or `--all`) — it deletes the runtime *and* closes the |
| 20 | strategy. A raw `strategy_close` MCP call closes the strategy but **leaves the runtime registered**, which |
| 21 | collides on the next deploy. "close all strategies / return funds to main" → `close.py --all`. |
| 22 | Pass the **strategy `id`** for a CATALOG strategy (what `senpi-strategy-discover` hands over, e.g. |
| 23 | `spider`) — it's fetched from the remote if not on disk. For a **locally-authored package, pass its |
| 24 | DIRECTORY path** (absolute is safest, e.g. `/data/workspace/strategies/<id>`): a bare id only resolves |
| 25 | locally relative to your CWD, so from anywhere else it becomes a remote catalog fetch — never what you |
| 26 | want for a package you just wrote. An on-disk package is authoritative; an invalid one surfaces its |
| 27 | real errors and is never silently replaced by a remote fetch. The scripts call MCP directly |
| 28 | (`scripts/mcp_client.py`, reads |
| 29 | `SENPI_AUTH_TOKEN`) + drive `openclaw senpi runtime …`. Mechanics + state machine: |
| 30 | [`references/lifecycle.md`](references/lifecycle.md). Manifest: [`references/strategy-yaml-schema.md`](references/strategy-yaml-schema.md). |
| 31 | |
| 32 | ## Deploy — three steps: create → runtime → verify (NOT live until `verify` passes) |
| 33 | |
| 34 | > **The loop is a gate, not a suggestion.** A strategy is LIVE only when `verify` returns `live` — every |
| 35 | > instance **runtime-running + scanner-active + DSL-wired + funded to what was requested**. If any step is |
| 36 | > incomplete, the strategy is **not live**; say so and fix the flagged component. Never report "live" off |
| 37 | > `registered` alone. |
| 38 | |
| 39 | **Step 0 — resolve which strategy.** The user's word ("spider") is a strategy **`id`**. To confirm it |
| 40 | exists, check the registry; no match → hand to **senpi-strategy-discover**: |
| 41 | ``` |
| 42 | curl -s https://raw.githubusercontent.com/Senpi-ai/senpi-skills/refs/heads/main/strategies/catalog.json |
| 43 | ``` |
| 44 | |
| 45 | **Step 0.5 — preflight (recommended).** `deploy.py validate <id>` reports every structural + render |
| 46 | issue in **one pass**, with **no side effects**, before you fund anything. The deployer **accepts the |
| 47 | flat single-instance layout** agents naturally scaffold — one `runtime.yaml` + `scanners/` at the |
| 48 | package root — by synthesizing the canonical `main` instance, so there's **no need to restructure into |
| 49 | `main/`**. Any remaining fix is named prescriptivel |