Skip to main content

Prediction Markets

Prediction-market conditions let an Auto query trigger on activity inside a prediction market. Two providers are supported:

  • Kalshi (source: "kalshi") — trigger on live trade prints (executed YES/NO price, trade flow, block trades) and market lifecycle (status, settlement result, settlement value), addressed by a full Kalshi market ticker.
  • Polymarket (source: "polymarket") — trigger on live outcome-token activity (last price, best bid/ask, last-trade size and aggressor side), addressed by an outcome-token asset_id. Polymarket exposes price/quote/trade methods only — there are no market-lifecycle methods.

Use a prediction-market condition when the trigger maps to a concrete data point on a market you can name (a Kalshi ticker or a Polymarket outcome-token id):

  • Prefer a prediction-market source over llm when the trigger is a supported method (price level, trade flow, status, or settlement). It evaluates on real trade/market events, not a scheduled natural-language guess.
  • Prefer it over price/ta when you care about the implied probability of an event resolving, not the spot price of a crypto asset.
  • Reach for llm only when the question is fuzzy and no prediction market expresses it.

Both sources use the full EQL condition form and obey the standard limits: they can be combined with other sources inside AND/OR groups, up to depth 3 and 10 leaf conditions. See Triggers.

Kalshi​

Exposed as EQL source: "kalshi". Kalshi conditions trigger on Kalshi prediction-market activity: live trade prints (executed YES/NO price, trade flow, block trades) and market lifecycle (status, settlement result, settlement value).

Open Markets Only​

Plans can only be created against an open market

At create time, Auto validates args.ticker against the catalog of open (tradeable) Kalshi markets. A ticker that is closed, determined, settled, or finalized is not in that catalog, and create/validate fails with EQL_INVALID_ARG_VALUE — the market "was not found or is not open".

Resolve a real, currently-open ticker before encoding the query. Do not invent or guess tickers. The full market ticker looks like KXBTC-26APR0803-T77799.99 (series + event + strike).

Note that lifecycle conditions are still useful on a market you are already watching. A plan created while a market is active can trigger as that same market moves to settled (via status) or resolves (result, settlement_value) within the plan's expiresIn window.

Condition Shape​

Kalshi conditions use the full EQL condition form. args contains exactly one field, ticker — the full Kalshi market ticker.

{
"source": "kalshi",
"method": "yes_price",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": "crosses_below",
"value": 0.4
}

Standard EQL limits apply: a kalshi condition can be combined with other sources inside AND/OR groups, up to depth 3 and 10 leaf conditions. See Triggers.

Trade-Backed Methods​

These read from live Kalshi trade prints. Each evaluates on the latest executed trade for the ticker.

MethodReturnsDescription
yes_pricenumber in [0, 1]Executed YES price in dollars — the live implied probability of the market resolving YES.
no_pricenumber in [0, 1]Executed NO price in dollars (implied probability of NO).
trade_sizenumber ≥ 0Number of contracts on that print.
taker_outcome_sideenum "yes" / "no"Which outcome the aggressor (taker) positioned for.
taker_book_sideenum "bid" / "ask"Same aggressor expressed in book terms: "bid" = YES-side pressure, "ask" = NO-side pressure.
is_block_tradebooleantrue when the print is a large negotiated off-book block trade.

yes_price and no_price are the core signals; they are the market's live read on how likely the event is. taker_outcome_side / taker_book_side / is_block_trade let you filter for who is trading and how, not just the price.

Market-Backed Methods​

These read from Kalshi market lifecycle updates rather than individual trades.

MethodReturnsDescription
statusenum "active" / "closed" / "determined" / "settled" / "finalized"Market lifecycle state. "active" is the only tradeable state.
resultenum "yes" / "no"Settlement outcome. Empty until the market resolves.
settlement_valuenumber ≥ 0Final settlement value in dollars; populated on settlement.

The lifecycle generally flows active → closed → determined → settled → finalized. A condition on status == "settled" (or result == "yes") is how you trigger downstream work the moment a market you've been watching resolves.

Operators by Method​

Operators are restricted per method:

Method(s)Allowed operators
yes_price, no_price> · < · >= · <= · == · != · crosses_above · crosses_below
trade_size, settlement_value> · < · >= · <= · == · !=
taker_outcome_side, taker_book_side, status, result, is_block_trade== · !=

Notes:

  • Only the price methods (yes_price, no_price) support the transition operators crosses_above / crosses_below. They evaluate a probability crossing a threshold, which is usually what you want for an alert.
  • Enum and boolean methods are equality-only (== / !=).
  • trade_size and settlement_value are numeric levels but have no cross operators.

Value Types and Enums​

value must be a literal that matches the method's type — Kalshi conditions do not support dynamic (field-vs-field) values.

Methodvalue typeAllowed values
yes_price, no_pricenumber0–1 (dollar price / implied probability)
trade_sizenumber≥ 0 (contracts)
settlement_valuenumber≥ 0 (dollars)
taker_outcome_sidestring enum"yes", "no"
taker_book_sidestring enum"bid", "ask"
statusstring enum"active", "closed", "determined", "settled", "finalized"
resultstring enum"yes", "no"
is_block_tradebooleanJSON true / false (not the strings "true"/"false")

Example Automations​

All examples are shown in the flattened title / description + conditions / actions / expiresIn shape. For HTTP calls, wrap conditions / actions / expiresIn under a top-level query key — see HTTP Request Wrapper.

1) Probability threshold crossing​

Alert when the market's YES probability falls through 40% — useful for catching a thesis breaking down on a market you hold a view on.

{
"title": "BTC < $77,799.99 — YES drops below 40%",
"description": "Fire when the Kalshi market's implied YES probability crosses down through 40%, signalling the market no longer expects this outcome.",
"conditions": {
"AND": [
{
"source": "kalshi",
"method": "yes_price",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": "crosses_below",
"value": 0.4
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Kalshi YES probability dropped below 40%" }
}
],
"expiresIn": "24h"
}

2) Aggressive flow into a near-certain market​

Combine a price filter with the taker side to catch aggressive YES buying into a market that is already pricing the outcome as near-certain — a "smart money is still piling in" signal.

{
"title": "Aggressive YES flow into a 90%+ market",
"description": "Fire when YES is already above 90% AND the aggressor is buying YES, indicating continued conviction buying near resolution.",
"conditions": {
"AND": [
{
"source": "kalshi",
"method": "yes_price",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": ">",
"value": 0.9
},
{
"source": "kalshi",
"method": "taker_outcome_side",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": "==",
"value": "yes"
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Aggressive YES flow into a 90%+ Kalshi market" }
}
],
"expiresIn": "24h"
}

3) Block-trade watcher​

Surface large negotiated block trades — a signal that a sizeable participant is taking a position.

{
"title": "Large block trade on Kalshi market",
"description": "Fire on off-book block trades larger than 500 contracts to flag institutional-size positioning.",
"conditions": {
"AND": [
{
"source": "kalshi",
"method": "is_block_trade",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": "==",
"value": true
},
{
"source": "kalshi",
"method": "trade_size",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": ">",
"value": 500
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
}
],
"expiresIn": "48h"
}

4) Settlement recap (lifecycle + LLM)​

Trigger the moment a market you are watching settles YES, then run an LLM action to write a short resolution recap and notify.

{
"title": "Kalshi market resolved YES — recap",
"description": "When the market settles with a YES result, generate a concise recap of what happened and why.",
"conditions": {
"AND": [
{
"source": "kalshi",
"method": "result",
"args": { "ticker": "KXBTC-26APR0803-T77799.99" },
"operator": "==",
"value": "yes"
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "llm",
"params": {
"action": "chat",
"message": "This Kalshi market just resolved YES. Write a concise recap explaining what resolved and what to watch next.",
"callback": {
"action": {
"type": "notify",
"params": { "message": "{{llm_output.analysisText}}" }
}
}
}
}
],
"expiresIn": "48h"
}

5) Builder Chat prompt​

You can let Builder Chat assemble the query. Give it the open ticker and the prediction-market signal you want:

Build an Auto query:
- title + description: short summary and the thesis behind this watch
- source: kalshi
- ticker: KXBTC-26APR0803-T77799.99 (already confirmed open)
- trigger when the YES implied probability crosses above 60%
- action: webhook to https://your-runner.example/auto/events
- one-time trigger, expires in 48h
If the ticker is not open or anything is unsupported, say so and return the closest supported query.

Validation Notes​

Error signalWhat it meansNext action
EQL_INVALID_ARG_VALUE on args.tickerTicker is not a currently-open Kalshi market (closed/settled/unknown).Resolve a currently-open full ticker and re-validate. Don't guess tickers.
Invalid enum valueA status/result/taker_* value outside its enum set.Use an exact enum value from Value Types and Enums.
Unsupported operatorAn operator not in the method's allowlist (e.g. crosses_above on trade_size, or > on status).Pick an allowed operator from Operators by Method.
is_block_trade type errorvalue passed as a string instead of a JSON boolean.Use JSON true / false, not "true" / "false".
Unknown methodMethod not in the supported set.Use a supported method.

Polymarket​

Exposed as EQL source: "polymarket". Polymarket conditions trigger on live outcome-token activity from Polymarket's prediction markets: last traded price, best bid/ask, and the size and aggressor side of the most recent trade. Unlike Kalshi, Polymarket exposes price and trade methods only — there are no market-lifecycle (status / result) methods.

Outcome-Token Tickers​

For Polymarket, args.ticker is the outcome token asset_id — the long numeric id of a single outcome (for example the YES token), not the top-level Polymarket market id. The market id is shared by both sides of a binary market and is not the routing key Auto uses.

At create time, Auto validates the token against Polymarket's live markets. An unknown or inactive token is rejected — the market "was not found or is not active". Resolve a real, currently-active outcome-token id before encoding the query; do not invent or guess ids.

Polymarket Condition Shape​

args contains exactly one field, ticker — the outcome-token asset_id.

{
"source": "polymarket",
"method": "price",
"args": { "ticker": "115556263888245616435851357148058235707004733438163639091106356867234218207169" },
"operator": "crosses_below",
"value": 0.4
}

Standard EQL limits apply: a polymarket condition can be combined with other sources inside AND/OR groups, up to depth 3 and 10 leaf conditions.

Polymarket Methods​

Each method takes a single ticker arg (the outcome-token asset_id) and reads from the live outcome-token price / quote / trade feed.

MethodReturnsDescription
pricenumber in [0, 1]Last traded probability / price for the outcome token.
bidnumber in [0, 1]Best bid for the outcome token (when present on the event).
asknumber in [0, 1]Best ask for the outcome token (when present on the event).
sizenumber ≥ 0Size of the last-trade update (when present on the event).
sideenum "BUY" / "SELL"Aggressor side of the last trade, in uppercase.

The feed mixes several event subtypes (price_change, best_bid_ask, last_trade_price, book), and not every field updates on every event — for example best_bid_ask updates bid/ask only, while last_trade_price updates price/size/side only. Design a condition around the specific field you need rather than assuming all fields move together on each update.

Polymarket Operators​

Operators are restricted per method:

Method(s)Allowed operators
price, bid, ask> · < · >= · <= · == · != · crosses_above · crosses_below
size> · < · >= · <= · == · !=
side== · !=

Only the price/quote methods (price, bid, ask) support the transition operators crosses_above / crosses_below. size is a numeric level with no cross operators, and side is equality-only.

Polymarket Value Types​

value must be a literal that matches the method's type. Polymarket conditions do not support dynamic (field-vs-field) values — because the feed mixes event subtypes and fields do not co-occur on every event, dynamic Polymarket targets are rejected at validation.

Methodvalue typeAllowed values
price, bid, asknumber0–1 (probability / price)
sizenumber≥ 0
sidestring enum"BUY", "SELL" (uppercase)

Polymarket Examples​

All examples are shown in the flattened title / description + conditions / actions / expiresIn shape. For HTTP calls, wrap conditions / actions / expiresIn under a top-level query key — see HTTP Request Wrapper.

1) Outcome price threshold crossing​

Alert when a single outcome token's implied probability falls through 40%.

{
"title": "Polymarket outcome drops below 40%",
"description": "Fire when the outcome token's last traded price crosses down through 0.40, signalling the market no longer expects this outcome.",
"conditions": {
"AND": [
{
"source": "polymarket",
"method": "price",
"args": { "ticker": "115556263888245616435851357148058235707004733438163639091106356867234218207169" },
"operator": "crosses_below",
"value": 0.4
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Polymarket outcome dropped below 40%" }
}
],
"expiresIn": "24h"
}

2) Aggressive buy flow (side + size filter)​

Catch a large BUY-side print on an outcome token — aggressive positioning into that outcome.

{
"title": "Large BUY-side Polymarket print",
"description": "Fire when the last trade on the outcome token is a BUY of more than 100 in size, flagging aggressive positioning.",
"conditions": {
"AND": [
{
"source": "polymarket",
"method": "side",
"args": { "ticker": "115556263888245616435851357148058235707004733438163639091106356867234218207169" },
"operator": "==",
"value": "BUY"
},
{
"source": "polymarket",
"method": "size",
"args": { "ticker": "115556263888245616435851357148058235707004733438163639091106356867234218207169" },
"operator": ">",
"value": 100
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Large BUY-side Polymarket print observed" }
}
],
"expiresIn": "24h"
}

3) Cross-outcome signal (AND across two tokens)​

Require two outcome tokens to satisfy their thresholds jointly — for example one outcome above 60% while another is below 30%.

{
"title": "Cross-outcome Polymarket signal",
"description": "Fire when outcome A trades above 0.60 AND outcome B trades below 0.30, confirming a joint move across two related outcomes.",
"conditions": {
"AND": [
{
"source": "polymarket",
"method": "price",
"args": { "ticker": "ASSET_ID_A" },
"operator": ">",
"value": 0.6
},
{
"source": "polymarket",
"method": "price",
"args": { "ticker": "ASSET_ID_B" },
"operator": "<",
"value": 0.3
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "notify",
"params": { "message": "Cross-outcome Polymarket signal hit" }
}
],
"expiresIn": "24h"
}

Polymarket Validation Notes​

Error signalWhat it meansNext action
Ticker not found / not activeargs.ticker is not a live Polymarket outcome token (unknown or inactive).Resolve a currently-active outcome-token asset_id and re-validate. Don't guess ids.
Unsupported operatorAn operator not in the method's allowlist (e.g. crosses_above on size, or > on side).Pick an allowed operator from Polymarket Operators.
Invalid side valueA side value other than "BUY" / "SELL", or the wrong case.Use uppercase "BUY" or "SELL".
Dynamic value on polymarketA field-vs-field dynamic value was used.Use a literal value; dynamic comparisons aren't supported for Polymarket in v1.
Unknown methodMethod not in the supported set (price, bid, ask, size, side).Use a supported method.

See the general iteration guidance in Validation Errors → Next Action: reshape and re-validate in a loop rather than abandoning the query.

Pair a prediction market with the asset it moves​

A prediction market tells you when the world changed. It doesn't have to be the end of the plan — it can be the trigger for an alert about the asset that catalyst moves.

A rate decision reprices on Kalshi in seconds. The assets it moves — the S&P, gold, the dollar, mega-cap tech — all trade as HIP-3 perps on Hyperliquid, 24/7, even when the cash equity market is closed. So a Kalshi condition can notify your runner about xyz:SP500 at 3am on a Sunday.

{
"conditions": {
"AND": [
{
"source": "kalshi",
"method": "yes_price",
"args": { "ticker": "<an open Kalshi Fed-decision market ticker>" },
"operator": "crosses_above",
"value": 0.6
}
]
},
"actions": [
{
"stepId": "step_1",
"type": "webhook",
"params": { "url": "https://your-runner.example/auto/events" }
}
]
}

This is the single highest-leverage pattern in Auto. It has its own page: Catalyst Triggers — how to pick the cheapest catalyst source, how to bridge a catalyst to the asset classes it moves, and five worked setups.