What calibration invariants must survive when prediction markets inform agent decisions?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session uses prediction market prices (Polymarket, Metaculus, internal forecasting markets) as inputs to decisions, and the markets may be miscalibrated, manipulated, or thin, requiring the agent to discount the price appropriately. Does not apply to strictly internal statistical forecasts, or markets with verified calibration and deep liquidity.

Core Distinction

The separation between **market price** (the current quoted probability) and **calibrated probability** (the probability adjusted for market-specific biases, manipulation, and liquidity). Relying on price creates the **Prediction Price Illusion**: the agent treats the market price as a calibrated probability and makes decisions that assume more reliability than the market actually provides, exposing the agent to manipulation or miscalibration.

What Was Observed

In forecasting-informed agent architectures, failing to verify calibration produces three primary failure modes:

  1. **Manipulation Exploitation:** A well-funded actor pushes the market price away from the true probability, the agent treats the price as truth, and the actor profits from the agent's decision.
  2. **Thin Market Distortion:** A low-liquidity market shows a price that reflects one trader's opinion, not a consensus, and the agent treats it as the calibrated probability.
  3. **Systematic Miscalibration:** The market historically overprices low-probability events (e.g., "will aliens be confirmed"), and the agent's decisions inherit this bias.

Recorded Elements

  1. **`market_calibration_receipt`:** The market's historical calibration profile (Brier score, reliability diagram), allowing the agent to adjust prices based on the market's known reliability.
  2. **`liquidity_depth_signature`:** The exact liquidity depth (order book size, recent volume) at the time of price observation, allowing the agent to detect thin markets.
  3. **`manipulation_detection_receipt`:** The cryptographic proof that the market price passes manipulation detection (e.g., price movement within historical volatility bands, no concentrated position dominance).
  4. **`calibrated_price_derivation_receipt`:** The exact transformation from raw market price to calibrated probability, including the calibration curve applied and the discount for manipulation risk.

Condition of Validity

* **Applies when:** The agent uses prediction market prices as inputs, prices can be miscalibrated or manipulated, and the agent's decisions are sensitive to calibration error. * **Does not apply when:** The market has verified calibration and deep liquidity (e.g., mature, well-audited markets), or the agent uses prices only as qualitative signals rather than quantitative probabilities.

Decision Boundary

  1. **Is the agent using prediction market prices?** If no, standard decision handling applies. If yes, proceed.
  2. **Does the market have a `market_calibration_receipt`?** If no, the agent cannot adjust for known biases. It must apply conservative priors.
  3. **Does the `liquidity_depth_signature` meet the agent's liquidity threshold?** If no, the price is likely distorted. The agent must widen its uncertainty interval.
  4. **Conversely, when can the agent use raw market prices?** Only when the market is verified to have high calibration accuracy (Brier < 0.15), deep liquidity, and no manipulation evidence.

Operational Effect

  1. **Manipulation Resistance:** Calibration and liquidity checks prevent decisions from being driven by manipulated prices.
  2. **Systematic Bias Correction:** Historical calibration data allows the agent to correct known market biases.
  3. **Uncertainty Quantification:** The agent's decision includes appropriate uncertainty based on market reliability.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class MarketVerdict(Enum):
    NO_MARKET_INPUT = auto()
    RAW_PRICE_TRUSTED = auto()
    CALIBRATED_PRICE_APPLIED = auto()
    PRICE_TOO_UNRELIABLE = auto()

@dataclass(frozen=True)
class MarketPrice:
    market_id: str
    raw_price: float
    brier_score: float
    liquidity_depth: float
    manipulation_detected: bool

@dataclass(frozen=True)
class CalibrationPolicy:
    max_trusted_brier: float
    min_liquidity_depth: float
    allow_manipulation: bool

@dataclass(frozen=True)
class CalibrationManifest:
    verdict: MarketVerdict
    calibrated_probability: float | None
    directive: str
    manifest_digest: str

class PredictionMarketCalibrationGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_market(
        cls, price: MarketPrice, policy: CalibrationPolicy
    ) -> CalibrationManifest:
        
        # Gate 1: Manipulation
        if price.manipulation_detected and not policy.allow_manipulation:
            return CalibrationManifest(
                verdict=MarketVerdict.PRICE_TOO_UNRELIABLE,
                calibrated_probability=None,
                directive=f"HALT: Market {price.market_id} shows manipulation. Reject price.",
                manifest_digest=cls._hash(f"MANIPULATION:{price.market_id}")
            )

        # Gate 2: Brier score (calibration quality)
        if price.brier_score > policy.max_trusted_brier:
            # Apply calibration adjustment: reduce confidence, widen uncertainty
            adjusted = 0.5 + (price.raw_price - 0.5) * 0.5
            digest = cls._hash(json.dumps({
                "market": price.market_id,
                "raw": f"{price.raw_price:.3f}",
                "brier": f"{price.brier_score:.3f}",
                "adjusted": f"{adjusted:.3f}"
            }, sort_keys=True))
            return CalibrationManifest(
                verdict=MarketVerdict.CALIBRATED_PRICE_APPLIED,
                calibrated_probability=adjusted,
                directive=f"PROCEED: Brier {price.brier_score:.2f} > {policy.max_trusted_brier:.2f}. Discounted to {adjusted:.2f}.",
                manifest_digest=digest
            )

        # Gate 3: Liquidity
        if price.liquidity_depth < policy.min_liquidity_depth:
            # Widen uncertainty for thin markets
            adjusted = 0.5 + (price.raw_price - 0.5) * 0.7
            digest = cls._hash(json.dumps({
                "market": price.market_id,
                "raw": f"{price.raw_price:.3f}",
                "liquidity": f"{price.liquidity_depth:.2f}",
                "adjusted": f"{adjusted:.3f}"
            }, sort_keys=True))
            return CalibrationManifest(
                verdict=MarketVerdict.CALIBRATED_PRICE_APPLIED,
                calibrated_probability=adjusted,
                directive=f"PROCEED: Thin market ({price.liquidity_depth:.2f}), widened to {adjusted:.2f}.",
                manifest_digest=digest
            )

        # Gate 4: Trust raw
        digest = cls._hash(json.dumps({
            "market": price.market_id,
            "raw": f"{price.raw_price:.3f}",
            "brier": f"{price.brier_score:.3f}",
            "liquidity": f"{price.liquidity_depth:.2f}"
        }, sort_keys=True))
        
        return CalibrationManifest(
            verdict=MarketVerdict.RAW_PRICE_TRUSTED,
            calibrated_probability=price.raw_price,
            directive=f"PROCEED: Price {price.raw_price:.3f} trusted (Brier {price.brier_score:.2f}, liquidity {price.liquidity_depth:.2f}).",
            manifest_digest=digest
        )