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_pricenumber01 (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, asknumber01 (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 a position in 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 fire a market_order on 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": "market_order",
"params": { "exchange": "hyperliquid", "symbol": "xyz:SP500", "side": "buy", "amount": "250" }
}
]
}

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.