Foundation / Real-time Patterns
Real-time Patterns
Three hooks that form the real-time subscription layer for AI-native treasury interfaces. All use only React — no third-party state libraries. All are React Strict Mode safe.
--ds-color-temporal) governs all real-time activity indicators. Gold (--ds-color-validation) for stale/threshold warnings. Green/red (--ds-color-outcome-*) for health outcomes.Hook 1 of 3
useAgentStream
Subscribes to a simulated SSE stream, delivering content in token-sized chunks. Returns accumulated chunks, stream lifecycle status, and time-to-first-token.
import { useAgentStream } from "@/hooks/useAgentStream";
const { chunks, status, latency, start, reset } = useAgentStream({
content: "Your agent response text here...",
chunkInterval: 40, // ms between chunks
chunkSize: 3, // chars per chunk
ttft: 320, // simulated time-to-first-token
});
// chunks: string[] — accumulated text pieces
// status: StreamStatus — "idle" | "streaming" | "complete" | "error"
// latency: number | null — ms to first token| Prop | Type | Default | Description |
|---|---|---|---|
| content | string | Finance commentary | Text to stream character by character |
| chunkInterval | number | 40 | Delay between each chunk delivery in ms |
| chunkSize | number | 3 | Characters delivered per chunk |
| ttft | number | 320 | Simulated time-to-first-token in ms |
Hook 2 of 3
usePositionFeed
Simulates live FX position ticks at a configurable interval with tunable volatility. Returns the current position book, the timestamp of the last tick, and the per-position delta.
| Pair | Rate | Notional | P&L | Trend |
|---|---|---|---|---|
| EUR/USD | 1.0847 | 5.0M | +12,340 | — |
| GBP/USD | 1.2634 | 2.5M | -4,210 | — |
| USD/JPY | 149.7200 | 10.0M | +31,500 | — |
| USD/CHF | 0.9051 | 1.0M | +880 | — |
import { usePositionFeed } from "@/hooks/usePositionFeed";
const { positions, lastUpdate, delta, running, pause, resume } = usePositionFeed({
interval: 1500, // tick frequency in ms
volatility: 0.3, // 0=frozen, 1=very volatile
});
// positions: Position[] — current live book
// lastUpdate: Date | null — timestamp of last tick
// delta: PositionDelta[] — rateDelta + pnlDelta per pair since last tick| Prop | Type | Default | Description |
|---|---|---|---|
| interval | number | 1500 | Milliseconds between ticks |
| volatility | number (0–1) | 0.3 | Rate movement magnitude. 0 = no movement, 1 = highly volatile |
Hook 3 of 3
useAgentHeartbeat
Polls a simulated agent status registry on a configurable interval. Marks agents as stale when they exceed the staleness window. Returns the agent list, last poll timestamp, and a top-level stale flag.
import { useAgentHeartbeat } from "@/hooks/useAgentHeartbeat";
const { agents, lastPing, stale, ping } = useAgentHeartbeat({
interval: 3000, // poll frequency in ms
staleAfterMs: 8000, // threshold before marking agent stale
});
// agents: AgentRecord[] — array with { id, name, role, status, lastSeenMs, currentTask }
// lastPing: Date | null — when the last poll completed
// stale: boolean — true if ANY agent is stale or offline
// ping: () => void — force an immediate poll| Prop | Type | Default | Description |
|---|---|---|---|
| interval | number | 3000 | Poll interval in ms |
| staleAfterMs | number | 8000 | Milliseconds without response before an agent is marked stale |
Usage Rules
When to use each hook
Agent reply panels, streaming response components, token-by-token chat interfaces.
Live FX monitor, real-time P&L panels, treasury position dashboards with tick data.
Multi-agent orchestration views, agent fleet status bars, ops dashboards monitoring autonomous worker health.
Do
✓ Use --ds-color-temporal for all streaming/polling indicators.
✓ Provide pause/resume controls on feeds that auto-update.
✓ Show a staleness warning (gold) before showing offline (red).
✓ Use tabular-nums for all rate and P&L values.
Don't
✗ Don't use red for streaming — blue owns in-flight activity.
✗ Don't skip cleanup on unmount — always clear timers and intervals.
✗ Don't poll faster than 1s intervals in production without backpressure.
✗ Don't show raw ms timestamps — format with toLocaleTimeString().
Related