The policy envelope
Every Veridex run operates under aPolicyEnvelope — the operator’s committed guardrail set, pinned before the run starts and recorded in the run’s policy_hash. The envelope specifies:
max_stake— maximum order size per decisionmax_stake_live_guarded— a tighter per-order cap that applies only on the live-guarded pathmin_edge_bps— minimum executable edge required to pass the post-quote gatemarket_allowlist— prefix-matched set of market keys the agent may tradevenue_allowlist— set of venues the agent may accessmax_slippage_bps— maximum tolerated slippage against the sealed reference pricemax_price— maximum acceptable decimal oddsmax_quote_age_s— maximum quote staleness before the post-quote gate rejects itcooldown_s— minimum seconds between consecutive orderscircuit_breaker_threshold— consecutive executed failures that trip the circuit breakerkill_switch— immediately denies all execution when set
policy_hash uses the canonical serializer, so the commitment is byte-stable and directly comparable to the rest of the evidence chain.
The two-phase policy gate
The policy gate splits checks into two phases around the venue quote. This prevents paying venue latency — or revealing intent to a venue — for an order that deterministic policy would kill anyway.Phase 1: Pre-quote checks
Before any venue I/O, Veridex checks:- Kill-switch — if set, deny immediately
- Circuit breaker state — if the breaker is OPEN, deny with zero venue I/O
- Stake cap — order size vs
max_stake - Live-only stake cap — order size vs
max_stake_live_guarded(live-guarded path only) - Market allowlist — the proposed market key must match a prefix in the allowlist
- Venue allowlist — the target venue must be in the allowlist
- Per-run order cap — total orders this run vs the configured limit
- Cooldown — time since the last order for this market
phase="pre_quote" policy result event and skips the venue quote entirely. All failing reason codes are collected — the gate never short-circuits on the first failure.
Phase 2: Post-quote checks
After fetching a live venue quote, Veridex checks:- Quote staleness — quote age vs
max_quote_age_s - Book-depth liquidity —
quoted_size < stakedenies (the book cannot fill the proposed size) - Slippage — actual slippage against the sealed reference price vs
max_slippage_bps - Executable edge — forward expected value at the actual quoted price, for the exact submitted size, vs
min_edge_bps - Max price — quoted decimal odds vs
max_price
human_approval_threshold escalates to REQUIRES_HUMAN rather than auto-approving.
The circuit breaker
The circuit breaker is a pure, immutable state machine with three states: CLOSED, OPEN, and HALF_OPEN.- OPEN state — denies all execution with zero venue I/O. An OPEN breaker prevents the run from making any further venue contact, not just blocking order submission.
- Only executed failures trip the circuit breaker — a policy denial, a dry-run simulated fill, and a human-approval escalation do not count as failures. Only a real attempted venue interaction that fails advances the failure counter.
- Recovery — the breaker transitions from OPEN to HALF_OPEN after a cooldown period (time is always injected, not wall-clock). A successful probe in HALF_OPEN fully closes the breaker; a failed probe returns it to OPEN.
breaker.allows() and mints the circuit_open deny reason — the execution runner constructs and threads the breaker cell but never makes circuit-breaker decisions itself. There is exactly one gate authority.
The live-money conjunction
A real Polymarket order requires every gate below to be satisfied simultaneously. Missing any one degrades the run to a dry simulation that records exactly why. 1. Mode is exactlylive_guarded
This is a structural conjunct, not a runtime check. The route selector arms only inside if execution_mode == LIVE_GUARDED. Any other mode — paper, dry_run, or any future mode value — falls through to the fake-adapter dry route by construction. No configuration can cause a non-live-guarded mode to place a real order.
2. Route arm gate: operator-supplied LiveExecutionDeps with live_ready == True
An operator must supply an armed adapter bundle. live_ready requires two operator-verified facts to be explicitly confirmed:
neg_risk_approved = True— the operator has independently confirmed the on-chain neg-risk exchange ERC-1155 approval. This cannot be verified by code; it requires on-chain inspection.fak_smoke_passed = True— the operator has run the 1-share FAK smoke (scripts/polymarket_smoke.py, gated byPOLYMARKET_SMOKE=yesandPOLYMARKET_WRITE_ENABLED) and received a realLIVE_GUARDEDsubmit/receipt. A degraded dry-run result counts as a failed smoke, not a pass.
live_ready is False unless both operator checks are explicitly True.
3. Adapter’s own lock: _require_armed
Even after the route arm gate approves, the PolymarketAdapter independently checks:
POLYMARKET_WRITE_ENABLEDis setdry_run = False- A write client is injected
- Circuit breaker check (OPEN = deny with zero venue I/O)
max_stake_live_guardedcap- Quote-size coupling (the quoted edge is priced for the exact size that submits — see below)
- Resolver raises
MarketUnavailableon any ambiguous or unknown market/side rather than guessing a token
No HTTP path arms real money
POST /competitions/{id}/start passes no live_deps argument by design. Real-money execution is operator-direct-only, by construction: an operator must build the armed adapter and the preflight verdict in code and supply them directly to start_competition. No HTTP request, no deployed agent, and no LLM proposal can arm the live path — the arming inputs do not exist on any wire surface.
Quote-size coupling
The venue quote is priced for the exact stake size that will submit. The slippage and executable edge the post-quote gate acts on reflect precisely the size being requested — there is no gap between the size the gate evaluates and the size the order sends. This prevents a scenario where a small test quote passes the gate but a large real order faces different economics.Honest degrade with recorded reasons
A configuredlive_guarded run that fails an arming check does not error. It runs as a dry simulation and emits an EXECUTION_ROUTE telemetry event recording: