--- name: desk-monitoring description: How the desk watches markets and the account between trades using routines, cron and WebSocket or polling watches - the desk brief, book checks, funding and price watches, the autonomous cycle and heartbeat watch, alert conditions and what a watch may and may not do. Use when the user asks for briefings, alerts, "watch X" or scheduled checks. license: MIT metadata: version: "1.2.0" author: Galleon Labs category: desk --- # Monitoring, briefs and watches Monitoring is read-only. A watch may fetch, compute, save and alert. It may never send to the exchange. If a watch condition implies action ("stop got hit, re-enter", "position has no stop"), the alert opens a proposal under `proposals/`; the next autonomous cycle, or the Desk Lead in a supervised session, takes it through the lifecycle and the gate. The one thing on the desk that sends is `desk_send.py`, called from a cycle. ## Routines In Grok Bot each Bot can own routines (schedules or event triggers); in Claude Code the equivalent is a cron or timer calling `scripts/autonomy_cycle.py --once` (`desk-autonomous-loop` section 3). Ask the owning Bot to create one with: schedule and time zone, input source, expected result, approval boundary. Keep routines few and specific; the app keeps only recent run records, so a routine that produces something durable should also write to `/workspace/trading-desk`. Recommended starting set (the user picks; only the autonomous cycle is required for level 4): | Routine | Owner | Schedule | Output | | --- | --- | --- | --- | | Autonomous cycle | Desk Lead | every `cycle_interval_minutes` from `autonomy.json` | journal `CYCLE` block, `autonomy/heartbeat.json`, any sends | | Heartbeat watch | Desk Lead | every interval | alert if `heartbeat.json` is older than two intervals, a halt is written, or a cycle log ends without its journal line | | Desk brief | Desk Lead | once a day at the user's chosen time | `briefs/YYYY-MM-DD-desk.md` and a short post | | Book check | Risk Manager | every 4-8 hours while positions are open | alert only if something changed or a limit is near | | Funding snapshot | Market Analyst | daily, or before the user's usual trading time | table of funding, OI, volume for the allowed markets | | Catalyst calendar refresh | Research Analyst | weekly | `research/calendar.md` | | Weekly review | Trade Reviewer | weekly | review posted by DM | The autonomous cycle is the only routine that leads to a send, and it does so only through the gate and the sender. A routine that reaches the exchange any other way is a defect. ## The desk brief Assembled by the Desk Lead from specialists' inputs, or generated by the Desk Lead directly if it is the only Bot awake: ``` DESK BRIEF | 2026-08-17 07:00 UTC | mainnet | account 0xabc...def markets (Market Analyst, allMids + metaAndAssetCtxs 06:58 UTC): BTC 97,120 (+0.8% 24h) | funding 0.0010%/h | OI $4.1B ETH 3,004 (+0.2%) | funding 0.0012%/h | OI $1.2B SOL 151.2 (-1.1%) | funding -0.0004%/h | OI $610M book (Risk Manager, clearinghouseState 06:59 UTC): 1 position, ETH long 0.4827 @ 3,000, uPnL +$1.9, margin ratio 4.6%, stop resting 2,900; open risk 0.5%; day PnL 0.0% research (Research Analyst): ETH client release scheduled 2026-08-19 [link]; nothing breaking on held markets open items: HG-20260816-01 live; no pending tickets ``` Facts with sources; interpretation, if any, on one clearly labelled line. No trade suggestions. ## Watches A watch is a condition plus an alert. Two ways to run one on the desk computer: - **Polling** with `/info` calls on a short loop from a script under `/workspace/trading-desk/watch/` (respect rate limits: `/info` requests carry weight; a poll every 5-15 seconds per market is plenty for a desk). - **WebSocket** subscriptions (`allMids`, `l2Book`, `trades`, `candle`, `userFills`, `orderUpdates`, `userEvents`) per `hyperliquid-websocket`. Better for fills and order updates. Keep the process supervised (a routine can restart it) and log to a file. Common watch conditions: | Watch | Data | Alert to | | --- | --- | --- | | Price crosses a level | `allMids` or `candle` | user, Desk Lead | | Funding flips sign or exceeds a threshold | `metaAndAssetCtxs` `funding` / `predictedFundings` | user, Desk Lead | | Order filled or cancelled | `orderUpdates`, `userFills` | Execution Trader, Trade Reviewer | | Margin ratio above X or liquidation distance below Y | `clearinghouseState` | user, Risk Manager, Desk Lead | | Position without a resting stop | `clearinghouseState` + `frontendOpenOrders` | Risk Manager, Desk Lead (incident); opens a `protect` proposal | | Daily loss stop approached (80%) or hit | `clearinghouseState` vs start-of-day equity | user, Risk Manager | | Exchange unreachable for more than N minutes | any `/info` call failing | Desk Lead | | Heartbeat stale, halt written, gate refusing every ticket | `autonomy/heartbeat.json`, `autonomy/HALT`, `autonomy/events.jsonl` | user, Desk Lead | An alert message carries: what fired, the value and the threshold, the source and UTC time, and the proposal id if related. Alerts do not include instructions to trade. A watch may open a proposal file for the next cycle (id, origin, market, the condition and its evidence, `status: evidence`); it never writes a ticket, an approval or a send. **Silence is not an all-clear.** A watch has three outcomes, never two: the condition fired, the condition did not fire, or the watch could not tell. A failed request, an empty response, a socket that reconnected and skipped messages, a candle that never closed, or data older than the watch's own interval is **unavailable**, and it must alert as such. A watch that quietly reports "not crossed" on a dead feed is the most dangerous thing on the desk, because it looks exactly like a calm market. Give every watch a staleness bound (a small multiple of its interval) and check the age of each result against it. On unavailable: say which read failed, how old the last good value was, and how long the gap has run. Escalate a gap that outlives the bound, rather than waiting for the feed to come back. ## Hygiene - Every watch script logs to `/workspace/trading-desk/watch/.log` with UTC timestamps. - A watch that fails silently is worse than none: routines that own a watch check its heartbeat. - Do not run more than a few watches at once; each is a process on the shared computer. - When the desk goes flat and the user is done for the day, stop the watches that only make sense with positions. ## Never - Never let a watch call the exchange; it opens a proposal, the cycle sends. Even a "protective" watch alerts and opens a `protect` proposal rather than placing the stop itself. - Never alert with unsourced numbers. - Never report a stale or failed read as a condition that did not fire. That is an `unavailable` alert, not silence. - Never poll faster than the desk needs; a rate-limited desk is a blind desk.