Skip to content

Live State UI & Update Flow

This page documents how the discretionary UI renders the agent’s trading environment and how it stays in sync with runtime mutations.

The discretionary live account panel is not SSE-driven.

It uses three update paths together:

  1. HTTP polling
  2. websocket invalidation events
  3. optimistic local mutation in the UI

That combination is what makes the panel behave like a realtime agent state display.

The backend route is:

  • GET /discretionary/live-state

Implemented in:

  • backend/services/autodiscretionary/index.ts

This route calls:

  • buildDiscretionaryRuntimeSnapshot(...)

The snapshot is the canonical backend runtime view for:

  • account
  • risk
  • active trades
  • watchers
  • time alerts
  • notes
  • prices
  • market hours
  • market conditions
  • drawdown lockout
  • health

On wallet/session open:

  • the UI fetches /discretionary/live-state
  • the initial live-state load is treated as blocking for that account view

After the first load, the panel refreshes on an interval:

  • currently every 10s

The discretionary runtime emits:

{ type: "live_state_changed", sessionId, reason }

The panel refetches when relevant discretionary runtime changes occur.

For user-initiated removes or changes, the UI mutates the visible live-state immediately on success before waiting for the next fetch.

The realtime chat and tool stream uses websocket deltas.

The live account panel uses:

  • HTTP snapshot fetches
  • websocket invalidation events

That makes it a snapshot UI with event-driven refresh hints, not a token-by-token streamed state panel.

LiveStatePanel shows a formatted UI version of the same underlying runtime data the agent sees, including:

  • account equity / margin
  • portfolio risk
  • market hours
  • market conditions
  • active markets
  • active trades
  • watcher pairs
  • time alerts
  • notes
  • drawdown lockout
  • health banners

So the panel is a human-readable projection of the agent trading environment.