Preflight
/install simmer-preflight
Simmer Preflight
Run client.preflight() before every real-money trade. One call returns:
- Who you are: agent ID, tier, venue resolved from your API key context
- Which wallet will sign: execution wallet, deposit wallet, signer mode (OWS / external key / managed)
- Spendable balance: venue-specific USDC or $SIM balance from the briefing
- Open exposure: sum of
current_valueacross your existing positions (real venues only for USD cap) - Cap check: whether
planned_amount + open_exposure_totalexceeds yourexposure_cap_usd - Risk alerts: any briefing risk signals (concentration, expiry, reliability)
- ok_to_trade: a single boolean — True if no blockers
When to use
Call preflight before every automated trade, especially:
- Before the first real-money order of a run
- Before scaling into a position beyond your initial size
- When your heartbeat wakes up after a long sleep (state may have changed)
Do not call it on every polling tick — it makes 3 API calls. Once per trade intent is correct.
Call it
from simmer_sdk import SimmerClient
client = SimmerClient.from_env(venue="polymarket")
result = client.preflight(
venue="polymarket", # venue to check (defaults to client.venue)
planned_amount=5.0, # USDC you plan to spend on this trade
exposure_cap_usd=100.0, # your total cross-venue exposure limit
)
if not result.ok_to_trade:
print(f"Preflight blocked: {result.blockers}")
# e.g. ["EXPOSURE_CAP_EXCEEDED"]
return
# Log for audit
ledger.record({
"preflight_id": result.client_preflight_id,
"ok": result.ok_to_trade,
"exposure_before": result.open_exposure_total,
"planned": result.planned_amount,
})
Result fields
| Field | Type | Description |
|---|---|---|
client_preflight_id |
str | UUID for your trade ledger — log before every order |
agent_id |
str | None | Agent UUID from /api/sdk/agents/me |
tier |
str | None | Account tier: "free" / "pro" / "elite" |
resolved_venue |
str | Normalised venue: "sim" / "polymarket" / "kalshi" |
execution_wallet |
str | None | EOA that signs trades (per-agent OWS wallet for Elite per-agent callers) |
deposit_wallet |
str | None | Deposit wallet address (DW cohort only; None for Cohort A) |
signer_status |
str | "ows" / "external_key" / "managed" |
spendable_balance |
float | None | Venue balance: pUSD/USDC (real) or $SIM (sim) |
gas_balance |
float | None | POL / SOL for gas — None in v0 (deferred to v1) |
open_exposure_total |
float | Sum of current_value across open positions (real venues only when cap is USD) |
exposure_cap_usd |
float | The cap you passed in |
planned_amount |
float | The planned trade size you passed in |
would_exceed_cap |
bool | True if open_exposure_total + planned_amount > exposure_cap_usd |
pending_alerts |
list[dict] | Risk alerts from briefing (normalised to {message: str}) |
ok_to_trade |
bool | True if no blockers |
blockers |
list[str] | Blocker codes (see below) |
warnings |
list[str] | Non-blocking advisories (fetch failures, skipped checks) |
Blocker codes (v0)
| Code | Meaning | Fix |
|---|---|---|
EXPOSURE_CAP_EXCEEDED |
open_exposure_total + planned_amount > exposure_cap_usd |
Wait for existing positions to resolve, or raise your cap |
WALLET_UNVERIFIED |
Real venue requested but real_trading_enabled is False, or no wallet configured |
Claim agent + link wallet in dashboard |
VENUE_UNSUPPORTED |
Venue string not recognised | Use "sim", "polymarket", or "kalshi" |
INSUFFICIENT_GAS |
Gas signal detected in risk_alerts (proxy only in v0) | Fund wallet with POL / SOL |
EXPOSURE_UNKNOWN |
Real venue + active cap, but positions fetch failed — fail-closed | Check connectivity or set exposure_cap_usd=0 to disable cap temporarily |
Blockers are additive — all blocking conditions are reported, not just the first.
Per-agent caller (Elite OWS)
For per-agent API keys, execution_wallet returns the per-agent OWS EOA — not the parent user's wallet. This is the SIM-2130 identity guarantee: the preflight returns the wallet that will actually sign the trade.
result = client.preflight(venue="polymarket", planned_amount=5, exposure_cap_usd=100)
print(result.execution_wallet) # 0xYourAgentOWS... (not parent user's wallet)
print(result.deposit_wallet) # 0xYourAgentDW... (per-agent DW if activated)
Exposure calculation
open_exposure_total sums current_value from /api/sdk/positions:
- For real venues (polymarket, kalshi): sums non-sim positions in USDC.
- For sim venue: sums sim positions in $SIM.
$SIM positions are never included in a USD cap check — they use virtual currency.
warnings[] vs blockers[]
blockers stop trading. warnings are informational — common examples:
briefing_fetch_failed: \x3Cerror>— balance / alerts unknown; check connectivitypositions_fetch_failed: \x3Cerror>— exposure may be understated; check rate limitsidentity_fetch_failed: \x3Cerror>— agent ID / tier unknown; API key may be invalid
If you see warnings, log them. Fetch failures on individual endpoints are gracefully handled — preflight returns best-effort data rather than throwing.
Pre-trade pattern (cookbook)
import os
from simmer_sdk import SimmerClient
EXPOSURE_CAP = float(os.environ.get("EXPOSURE_CAP_USD", "100"))
client = SimmerClient.from_env(venue="polymarket")
def safe_trade(market_id: str, side: str, amount: float):
pf = client.preflight(
venue="polymarket",
planned_amount=amount,
exposure_cap_usd=EXPOSURE_CAP,
)
if not pf.ok_to_trade:
print(f"Preflight blocked ({pf.blockers}), skipping trade")
return None
if pf.warnings:
print(f"Preflight warnings: {pf.warnings}")
# Log preflight before order submission
print(f"Preflight OK — id={pf.client_preflight_id} "
f"exposure={pf.open_exposure_total:.2f}+{amount:.2f}/{EXPOSURE_CAP}")
return client.trade(market_id=market_id, side=side, amount=amount)
Cadence
Call once per trade intent — not on every poll cycle. The preflight makes 3 API calls (/agents/me, /briefing, /positions), each counting toward your rate limits.
Scope
Preflight is read-only. It never signs, trades, redeems, or mutates settings. It is safe to call in any context including paper-trading mode (positions will reflect simulated holdings).
v0 limitations
gas_balanceis alwaysNone— on-chain RPC not available in the SDK client. Use the dashboard to verify POL / SOL balance.INSUFFICIENT_GASis only detected if the briefing risk_alerts mention gas explicitly — not from an on-chain query.- Server-side
preflight_id(stable, storable) deferred to v1. - MCP tool exposure deferred to v1.
Links
- API reference: docs.simmer.markets/api/preflight
- Wallet cohort guide: docs.simmer.markets/wallets
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install simmer-preflight - After installation, invoke the skill by name or use
/simmer-preflight - Provide required inputs per the skill's parameter spec and get structured output
What is Preflight?
Pre-trade readiness check for autonomous agents. One call returns wallet identity, venue status, spendable balance, open exposure, and a structured ok_to_tra... It is an AI Agent Skill for Claude Code / OpenClaw, with 14 downloads so far.
How do I install Preflight?
Run "/install simmer-preflight" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Preflight free?
Yes, Preflight is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Preflight support?
Preflight is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Preflight?
It is built and maintained by Simmer.Markets (@simmer); the current version is v0.3.0.