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.
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.
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
--venueflag - 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_commandSend command to a running daemon. Actions: pause, resume, scan_now, adjust_trigger.
set_wake_conditionCreate alert rule. Types: price (ticker crosses threshold), time (at timestamp), llm (natural language evaluated by LLM each cycle).
check_daemon_alertsRead and clear pending observations and alerts from all running daemons.
runtime_start / runtime_stop / runtime_statusControl 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_deleteRead, write, list, grep, and delete files. All paths sandboxed to workspace root.
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_wakeSchedule a future action: prompt (ask the LLM), tool (run a specific tool), or check (notification only). Supports auto-repeat.
list_wakes / cancel_wakeView 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:
Usage tracked in ~/.sf/bus/cost/smart-usage.jsonl. Budget enforced per-call — if exceeded, daemons fall back to mechanical mode.