Agent Runtime

Multi-daemon architecture for autonomous prediction market trading.


Architecture

The agent runtime is a set of coordinated processes. Your main agent orchestrates background daemons that monitor markets, evaluate triggers, and execute autonomously.

agent — interactive TUI, sets conditions, reads alerts
runtime — intent execution, trigger evaluation, smart scans
quoteengine — automated market making, WebSocket-driven bid/ask quoting
telegram — push notifications, mobile agent bridge
watch — market monitoring, flow detection, cross-venue
~/.sf/bus/ — file-based message bus for IPC

Smart Mode

--smart adds an LLM intelligence layer to daemons. Uses a cheap model (Haiku 4.5) via the proxy API for ~$0.0001/call.

Soft Conditions

Intents can have natural language conditions. When a hard trigger fires, the runtime asks the LLM whether the condition is met before executing.

sf intent buy KXFEDDEC2509 500 --price 36 \
  --trigger below:40 \
  --soft "only if oil sustained above $95 and no dovish fed signals"

Periodic Smart Scan

Every ~5 minutes, the runtime summarizes all active intents + market state and sends observations to the agent via the message bus. Catches things mechanical triggers miss: correlated risks, spread anomalies, regime shifts.

Wake Conditions

The agent can set rules for when to be alerted. Price thresholds and time triggers are evaluated mechanically. Natural language conditions are evaluated by LLM each cycle.

# Inside sf agent, the LLM can call:
set_wake_condition({
  description: "alert if bid depth collapses on KXFEDDEC",
  type: "llm",
  condition: { prompt: "bid depth < 100 contracts at any price level" }
})

Message Bus

Daemons communicate via ~/.sf/bus/. No Redis, no sockets — just JSON files with atomic rename.

~/.sf/bus/inbox/ ← agent commands to daemons
~/.sf/bus/outbox/ ← daemon alerts to agent
~/.sf/bus/wake/ ← wake condition definitions
~/.sf/bus/presence/ ← agent heartbeat (30s)
~/.sf/bus/cost/ ← LLM usage tracking

Messages have TTL (default 1 hour). Expired messages are auto-cleaned. If the agent is inactive and an alert is critical, it escalates to Telegram.


QuoteEngine v2 — multi-venue

Automated market making daemon. Places bid+ask on Kalshi and Polymarket, auto-requotes on fills and orderbook moves. Venue is auto-detected from the marketId shape — Kalshi tickers (KX...) or Polymarket YES tokenIds (decimal uint256, or 0x-hex which is auto-normalized). Supports biased quoting, paper trading with simulated fills, dynamic spread, and thesis-driven auto-bias.

Key Features

  • Multi-venue: Kalshi + Polymarket in the same daemon, no --venue flag
  • Kalshi: WebSocket-driven fills, orderbook deltas, order state in real-time (<100ms)
  • Polymarket: 5s orderbook poll (WebSocket integration deferred to v2)
  • Kalshi requote via amend_order — atomic, no naked exposure. Polymarket falls back to cancel-and-replace (no amend endpoint)
  • Inventory skew: widens spread on heavy side
  • Bias mode: manual (+/-N¢) or thesis-driven auto-bias from edge data
  • Paper trading: simulated fills from live book data (triggers when market crosses quote levels)
  • Dynamic spread: min/max clamping + post-fill fade widening
  • Layered quotes: multiple price levels per side
  • Requote debounce: configurable delay to avoid being gamed by fast book flickering
  • Kalshi Order Group circuit breaker + post_only + cancel_order_on_pause
  • Bus alerts: fills, stop loss, WS disconnect pushed to agent

Safety: WS Disconnect

On WebSocket disconnect: immediately cancel ALL resting orders via REST, then reconnect, reconcile state, and resume. Never reconnect-then-cancel.

# Start QuoteEngine daemon
sf quoteengine start --daemon

# Paper trading with bias (Kalshi)
sf quote create kalshi:KXRECSSNBER-26 --spread 2 --size 5 --paper --bias 2

# Paper trading on Polymarket (poly: prefix or bare token id, venue auto-detected)
sf quote create poly:0x66abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678 --paper --spread 2 --size 5

# Thesis-driven auto-bias (manual: pin a specific thesis)
sf quote create TICKER --spread 3 --size 10 --thesis-id UUID

# Auto-pick the best matching thesis for this ticker (no UUID needed)
sf quote create kalshi:KXBTC-26APR0817-B69875 --spread 2 --size 5 --paper --thesis-auto

# Post-fill fade + layered quotes + debounce
sf quote create TICKER --spread 2 --fade 3 --layers 3 --requote-delay 200

# Check status (shows bias, spread, P&L, fills)
sf quoteengine status

Quick Start

# Start smart runtime daemon
sf runtime start --smart --daemon

# Start QuoteEngine daemon
sf quoteengine start --daemon

# Start telegram bot
sf telegram --daemon

# Launch agent (auto-connects to all daemons)
sf agent

# Inside agent: set a wake condition
> "wake me if any recession contract moves more than 5 cents"

# Inside agent: start market making
> "create a paper quote on KXRECSSNBER-26 with 2 cent spread"

# Inside agent: check daemon observations
> "any alerts from the quoteengine?"

# Inside agent: send command to runtime
> "tell the runtime to run a scan now"

Configuration

# ~/.sf/config.json
{
  "smartDaemons": true,           // enable by default (no --smart flag needed)
  "smartModel": "anthropic/claude-haiku-4.5",  // cheap, fast
  "smartScanInterval": 10,        // scan every 10 runtime cycles (~5 min)
  "smartBudgetUsd": 1.00,         // monthly LLM budget cap
  "smartEscalateToTelegram": true, // critical alerts → Telegram when agent offline
  "syncPositions": true           // push local positions to heartbeat on agent start
  // closedLoop is per-thesis (set via sf heartbeat <id> --closed-loop-entry/exit)
}

Agent Tools

daemon_command

Send command to a running daemon. Actions: pause, resume, scan_now, adjust_trigger.

set_wake_condition

Create alert rule. Types: price (ticker crosses threshold), time (at timestamp), llm (natural language evaluated by LLM each cycle).

check_daemon_alerts

Read and clear pending observations and alerts from all running daemons.

runtime_start / runtime_stop / runtime_status

Control the execution runtime daemon. Logs to ~/.sf/runtime.log.


Workspace Filesystem

The agent has a local filesystem at ~/.sf/workspace/. Use it as a scratchpad for notes, analysis, and data exports. Shared across TUI and Telegram.

fs_read / fs_write / fs_list / fs_search / fs_delete

Read, write, list, grep, and delete files. All paths sandboxed to workspace root.

~/.sf/workspace/
context/ ← conversation history (JSONL, shared TUI/Telegram)
notes/ ← agent working notes
analysis/← longer analysis documents
data/ ← CSV, JSON exports

Self-Wake

The agent can schedule itself to wake up after idle. Useful for monitoring developing situations, periodic checks, or timed reminders. Race-safe: wakes only fire when the user is not mid-conversation.

schedule_wake

Schedule a future action: prompt (ask the LLM), tool (run a specific tool), or check (notification only). Supports auto-repeat.

list_wakes / cancel_wake

View and cancel scheduled wakes.

# Inside sf agent:
> "check oil prices every 30 minutes and alert me if WTI drops below $90"
# Agent calls schedule_wake(30, 'prompt', 'Check WTI...', repeat: 30)

Voice I/O

Talk to the agent with voice. TTS and STT powered by Cartesia via server proxy.

Voice Input (Speech-to-Text)

TUI/Plain: type /voice to start recording, /voice again to stop, transcribe, and send. Requires sox (brew install sox).

Telegram: send a voice message directly — auto-transcribed and processed.

Voice Output (Text-to-Speech)

The agent has a speak tool to read text aloud. Useful for alerts, summaries, or hands-free workflows.


Position Sync & Closed Loop

Position Sync

When enabled, the agent pushes your Kalshi/Polymarket positions to the server on startup. The heartbeat monitor can then see your real exposure during evaluations — instead of just "edge +15", it says "edge +15, you hold 500 contracts, P&L +$115".

# Enable in ~/.sf/config.json
"syncPositions": true

# Positions are cross-matched with thesis edges server-side.
# Only positions that match a thesis edge are stored.
# Syncs once per agent session (on startup).

Closed Loop

Two independent flags per thesis. Entry auto-creates BUY intents when strategy entry conditions are met. Exit auto-creates SELL intents when stop-loss or take-profit conditions are met (requires synced positions). Both default off. All auto-created intents have autoExecute: false.

# Entry: strategy.entryBelow=35, price hits 34¢ → BUY intent
sf heartbeat <id> --closed-loop-entry

# Exit: strategy.stopLoss=20, price hits 19¢ → SELL intent
# Exit: strategy.takeProfit=60, price hits 62¢ → SELL intent
sf heartbeat <id> --closed-loop-exit

# Both:
sf heartbeat <id> --closed-loop-entry --closed-loop-exit

# Backtest before enabling:
sf backtest KXFED --entry-below 35 --stop 20 --tp 60 --days 30

Backtest

Test strategy parameters against historical prices before going live. Pure computation, zero LLM cost. Also available as an agent tool — the agent can run backtests and interpret results during conversation.


Cost

Smart mode uses Haiku 4.5 via proxy. Typical costs:

Soft condition evaluation: ~$0.0001/call
Periodic scan: ~$0.0008/call
Wake condition (LLM type): ~$0.0005/call
Default budget: $1.00/month (~1000 calls)

Usage tracked in ~/.sf/bus/cost/smart-usage.jsonl. Budget enforced per-call — if exceeded, daemons fall back to mechanical mode.