The architecture in one diagram
The stack has five layers. Skipping any of them produces a brittle system or an unsafe one.
| Layer | Component | Responsibility |
|---|---|---|
| 1 | Inputs | Elo ratings, news feed, Polymarket order book |
| 2 | LLM consensus | Claude + GPT + Gemini decide on the trade |
| 3 | Policy layer | Per-trade caps, per-market caps, kill switch |
| 4 | Polymarket adapter | py-clob-client signs and submits orders |
| 5 | Audit log | Decision trace per trade, append-only storage |
Layer 1: Inputs
Three real-time feeds, each with a different cadence.
- Elo ratings. Refresh weekly. Sources: FiveThirtyEight's SPI archive, the eloratings.net feed, or your own fitted ratings on FBref data. Treat as the prior.
- News. Filter for the 48 competing teams. RSS feeds from ESPN, BBC, Athletic, Marca, and team-specific accounts work. An LLM filters relevance and classifies severity (squad injury → high; manager press conference → low).
- Polymarket order book. py-clob-client exposes
get_orderbook(market_id). Poll every 30s during match hours, every 5min off-hours.
Layer 2: The LLM consensus
The agent loop. Pseudocode:
for market in active_markets: inputs = {elo, news, orderbook, prev_decisions}; votes = parallel(claude.decide, gpt.decide, gemini.decide); decision = weighted_consensus(votes); if decision.edge > THRESHOLD: place_order(decision)
The non-trivial pieces: structured-output schema (each model must return side, confidence, target_size, reasoning as validated JSON), per-regime weighting (different model votes count differently for group-stage vs knockout), and a confidence floor below which the agent stands down.
Layer 3: The policy layer
The single most important layer for keeping the bot from bankrupting you. Hardcoded caps in code, not in the prompt:
- Per-trade size cap. Reject any order above $X USDC. Set in config; never override at runtime.
- Per-market position cap. Reject if resulting position would exceed $Y USDC on a single market.
- Per-team aggregate cap. Sum of positions across all WC markets touching team T cannot exceed $Z.
- Per-hour throughput cap. Maximum N trades per rolling 60 minutes. Catches runaway agents.
- Kill switch. A single endpoint or env-var that disables order placement instantly. Test this monthly.
The caps run before the Polymarket adapter ever sees the order. Even if Claude hallucinates and asks for a $1M Argentina-wins bet, the policy layer rejects it. Without this layer, multi-LLM consensus is not enough.
Layer 4: The Polymarket adapter
py-clob-client is the standard library. Signs orders with the user's wallet, submits to Polymarket's CLOB on Polygon, returns the order ID and status. Run on a wallet that holds only the trading capital: never the user's long-term holdings. If the wallet is compromised, the loss is bounded to the operational balance.
For US users, the equivalent is the Kalshi or Polymarket US REST API. The interface differs; the policy-layer architecture above is identical.
Layer 5: The audit log
Every decision, every input, every model vote, every policy decision, every order, every fill: append-only to S3 with object lock, or local file with rotation. The audit log is what lets you debug a bad trade, prove a tax position, and improve the agent's prompts week-by-week.
Minimum schema per entry: timestamp, market ID, input snapshot, model votes (with reasoning), consensus decision, policy decision, order details, fill details (when applicable), realised PnL (when position closes).
A worked example: group-stage strategy
A hypothetical walkthrough with illustrative numbers, not a live trade recommendation. The bot is configured to trade group-stage winners. Group A has the US, Mexico, Canada (joint hosts) and one playoff qualifier.
- Inputs: Elo ratings give US 45%, Mexico 32%, Canada 15%, Playoff 8% to win the group. Polymarket prices imply US 52%, Mexico 28%, Canada 12%, Playoff 8%. News: no major injuries; US has home-soil narrative.
- Multi-LLM consensus: Claude and GPT agree the market overstates the host effect; Gemini reads recent friendly results as more bullish. Weighted consensus: US 48% true probability.
- Decision: the consensus reads the US as over-priced by 4 percentage points; the example bot sells at the quoted 52%.
- Policy check: trade size $500 (under $1k cap); position resulting $500 (under $2k cap); throughput 1/hr (under 5/hr cap). Pass.
- Polymarket adapter places the order. Fill at 51.8%.
- Audit log records the full chain.
The legal lines
Three things to verify before deploying:
- Polymarket International is geographically restricted from US residents. If you are in the US, your agent must run against Polymarket US or Kalshi, not the international venue. Compliance is your responsibility.
- Tax treatment varies by jurisdiction. In the US, Kalshi sports event contracts are taxed as commodities futures; Polymarket positions are taxed as digital assets. Maintain the audit log accordingly.
- Algorithmic trading is permitted on both Polymarket and Kalshi. Sportsbooks (DraftKings, FanDuel) prohibit it and limit accounts that show edge. The bot is for prediction-market venues only.
The build-vs-buy question
Two-to-four engineer-weeks for a working v1, plus a permanent operational tail, model versions change, the API drifts, edge cases appear during the actual tournament. Worth it if you have a specific strategy you can't express otherwise. Not worth it if your goal is to start trading the World Cup, by the time the bot works, the tournament is half over.
NickAI's agentic OS runs the equivalent of the architecture above as a configurable runtime: non-custodial, multi-LLM consensus, policy layer with caps, per-trade audit log, integrated with Polymarket and Kalshi by default. The tradeoff is the standard build-vs-buy one: full control vs. months of your life.