Heartbeat engine
Your thesis runs while you sleep
Prices, news, signals, causal models — pulled every 15 minutes across Kalshi and Polymarket. One call returns everything that matters. Your agent pushes observations anytime.
Write a thesis in plain language
$ sf create "Iran war sustains oil above $100, recession by Q3"
✓ Causal tree built — 6 nodes
n1 Hormuz closure persists ████████░░ 85%
n2 Oil sustained above $100 █████████░ 91%
n3 Fed constrained by stagflation███████░░░ 72%
n4 Consumer spending contracts ██████░░░░ 65%
n5 GDP contraction Q3 ██████░░░░ 63%
n6 NBER declares recession █████░░░░░ 55%
✓ 49 markets mapped across Kalshi + Polymarket
✓ 12 edges found — largest: WTI T150 +36¢
✓ Heartbeat started — next cycle in 15 minNatural language becomes a causal tree of testable claims. Each node has a probability and maps to real contracts. The heartbeat starts immediately.
Every 15 minutes, autonomously
Heartbeat #847 — 11:14 UTC
[news] 3 queries — 2 regular, 1 adversarial
▲ WSJ: Hormuz effectively closed to tanker traffic
▼ Trump announces 5-day strike pause
— IEA: "major threat worse than 1970s oil shock"
[prices] 49 markets rescanned
WTI T135 58¢ → 62¢ ▲ +4¢ signal injected
WTI T150 36¢ → 38¢ ▲ +2¢
Recession 32¢ → 35¢ ▲ +3¢ signal injected
[milestones] 3 upcoming
18h WTI weekly settle
3d OPEC emergency meeting
5d CPI May print
[eval] 5 signals consumed → confidence 89% ▲ +2Kill conditions checked:
✓ Ceasefire deal signed — no
✓ Hormuz reopens to tankers — no
✓ Trump lifts Iran sanctions — no
✓ Oil drops below $80 — no
Adversarial query: "iran ceasefire deal progress"
→ No credible path to resolution foundNews scan, price rescan, milestone detection, kill condition check, adversarial search, LLM evaluation — all automatic. Signals that move prices by 3¢+ get injected. The LLM consumes them and updates the causal tree.
One call returns everything
$ sf context f582bf76 --json
{
"confidence": 0.89,
"confidenceDelta": 0.02,
"nodes": [
{ "id": "n1", "label": "Hormuz closure persists", "prob": 0.85,
"prevProb": 0.82, "reason": "WSJ confirms tanker blockade" },
...
],
"edges": [
{ "market": "WTI T150 YES", "price": 38, "implied": 74,
"edge": 36, "spread": 1, "depth": 2400,
"liquidity": "high", "type": "consensus_gap" },
...
],
"evaluation": {
"summary": "Hormuz closure confirmed by WSJ...",
"signalsConsumed": 5,
"trackRecord": { "hitRate": 67, "edgesTracked": 12 }
},
"positions": [...],
"updatedAt": "2026-03-23T11:14:00Z"
}Causal tree with updated probabilities, edges with live prices and orderbook, evaluation summary, track record, positions — all in one response. Your agent doesn't assemble state. It reads it.
Your agent pushes back
# Your agent observes something the heartbeat missed
$ sf signal f582bf76 "Brent just broke $100 — first time since 2022"
✓ Signal queued — type: user_note
Will be consumed in next evaluation cycle
# Or force immediate evaluation when it matters
$ sf evaluate f582bf76
✓ Evaluation complete
Confidence: 89% → 91% ▲ +2
n2 (Oil above $100): 91% → 95%
New edge surfaced: Brent T110 YES — +28¢The heartbeat runs autonomously but your agent can inject observations anytime. Force an evaluation when something big happens — don't wait for the next cycle.
The heartbeat gives your agent context. What it does with that context is up to your execution strategy.