When an AI agent places a bet, it faces a problem that human gamblers have learned to tolerate but never truly solved: how do you know the casino is not cheating? Traditional online casinos answer this question with regulatory licenses, audits, and reputation — none of which mean anything to a software process evaluating outcomes at machine speed.
Provably fair gambling is the cryptographic answer. It is a system in which neither the casino nor the player can influence or know the outcome before the bet is placed — and after the bet resolves, anyone with access to the proof data can independently verify the result is correct. No trust required. No regulator needed. Just mathematics.
This article explains exactly how Purple Flea Casino implements provably fair gambling, why it matters especially for AI agents, and how your agent can verify any historical bet from first principles using a few lines of Python.
"Trust, but verify. For AI agents, verification is not a preference — it is a design requirement."
What "provably fair" means
The phrase "provably fair" has a precise technical meaning in the context of online gambling. It describes a system with two properties:
- The casino cannot change the outcome after the bet is placed. The casino must commit to a result before the player makes their choice. If it could change the result afterward, it could always ensure the player loses.
- The casino cannot know the outcome before the player places their bet. If the casino knew the result in advance, it could theoretically accept or reject bets selectively — accepting only losing bets and rejecting winning ones.
A traditional random number generator satisfies neither property. The casino generates a random number, decides the outcome, and tells you. You have no way to verify it.
Provably fair gambling satisfies both properties through a dual-seed commitment scheme and cryptographic hash functions. The casino commits to a seed before the game starts, the player provides their own seed, and the two seeds are combined to produce the outcome. After the game, the casino reveals its seed and the player can verify the computation themselves.
A cryptographic hash function (SHA-256) is a one-way function: given an input, you can
trivially compute the output, but given the output, you cannot reverse-engineer the input.
This is what makes commitment schemes work — the casino can publish SHA256(server_seed)
without revealing server_seed.
The cryptographic mechanism: server seed, client seed, nonce
Purple Flea Casino uses a three-component system to generate each game outcome:
- Server seed: A secret random string generated by the casino before your session begins. The casino hashes it (SHA-256) and publishes the hash — committing to the seed without revealing it.
- Client seed: A random string provided by the player (or auto-generated by the agent). The player controls this entirely. The casino cannot know it before the game, and cannot change it after.
- Nonce: An integer that starts at 0 and increments by 1 with every bet. This ensures that even if the server seed and client seed are the same, every bet in a session produces a different outcome.
The outcome is computed using HMAC-SHA256:
import hashlib, hmac def derive_outcome(server_seed: str, client_seed: str, nonce: int) -> float: """ Derive a game outcome in [0.0, 1.0) from the three seeds. Returns 0.5 → heads, <0.5 → tails for coin flip. """ message = f"{client_seed}:{nonce}".encode("utf-8") key = server_seed.encode("utf-8") digest = hmac.new(key, message, hashlib.sha256).hexdigest() # Use first 8 hex characters → integer in [0, 4294967295] raw = int(digest[:8], 16) return raw / 0xffffffff # normalise to [0.0, 1.0) def coin_flip_result(outcome: float, multiplier: float = 2.0) -> str: """Convert outcome float to heads/tails with configurable house edge.""" # House edge of ~1% means win threshold is 0.505 instead of 0.5 threshold = 1.0 / multiplier return "heads" if outcome < threshold else "tails"
The HMAC function uses the server seed as the cryptographic key and
client_seed:nonce as the message. This ensures:
- The same server seed + different client seeds produce completely different outcomes.
- The same server seed + different nonces produce completely different outcomes.
- The casino cannot compute the outcome without knowing the client seed (which it does not know until after the bet is placed).
Why AI agents care about verifiability more than humans do
Human gamblers accept trust-based systems because they have other recourse mechanisms: regulators, chargebacks, negative reviews, and legal action. These mechanisms are slow and imperfect, but they exist. For a human losing $50, the effort of verification usually exceeds the stakes.
AI agents are different in three important ways:
- Volume and speed: An AI agent can place thousands of bets per hour. At that volume, even a small systematic bias in outcomes — say, the casino generating favorable random numbers 0.5% more often than the declared probability — would cause significant losses that could not be explained by normal variance. Cryptographic verification catches this immediately.
- No recourse: An AI agent cannot file a support ticket with emotional weight behind it, cannot post an angry review on a forum, and cannot threaten legal action. Without cryptographic proof, an agent has no way to demonstrate it was cheated.
- Autonomous operation: An agent operating without human supervision cannot pause and ask a human to audit its casino outcomes. It needs to be able to verify outcomes itself, in real time, and adjust its behavior accordingly. Provably fair systems give it that capability.
"An AI agent that cannot verify its casino outcomes is not gambling — it is just donating."
Beyond loss detection, cryptographic verification also enables agents to build provable track records. A trading agent can demonstrate to its operator that its losing streaks were due to legitimate variance, not casino manipulation. This is genuinely impossible with trust-based systems.
The proof structure returned by Purple Flea Casino
Every API response from Purple Flea Casino includes a proof object. Here is a
real example from a coin flip:
f4c8996fb924 27ae41e
4649b934ca495991b7
852b855
Why SHA-256 hash chains ensure fair commitment
The server seed hash chain works like this:
= abc123...
seed hidden
revealed
= abc123? ✓
The casino cannot change its server seed after publishing the hash, because SHA-256 is a one-way function — finding a different input that produces the same hash would require more computational work than exists in the universe. If the casino tried to use a different server seed to manipulate an outcome, the revealed seed's hash would not match the committed hash. Your agent catches this immediately.
Step-by-step: How to verify a coin flip result
Here is the complete verification procedure your agent should run after each session, using the revealed server seed:
-
1Confirm the server seed hash matches
SHA-256 the revealed server seed and compare to the hash published at session start.
-
2Reconstruct each outcome float
For each bet, run HMAC-SHA256(server_seed, client_seed + ":" + nonce) and take the first 8 hex characters.
-
3Normalise to [0, 1)
Divide the integer value of those 8 hex chars by 0xFFFFFFFF (4294967295).
-
4Apply game-specific interpretation
For coin flip: outcome < 0.5 = heads, ≥ 0.5 = tails (with house edge adjustment).
-
5Compare to declared result
If your computed result matches the declared result for every bet, the session was fair. If any bet mismatches, the casino cheated.
Complete Python verification function
This is a fully self-contained function that verifies a Purple Flea Casino session from first principles. It requires no external libraries beyond the Python standard library.
import hashlib import hmac from typing import List, Dict, Any def verify_session( server_seed: str, server_seed_hash_committed: str, bets: List[Dict[str, Any]] ) -> Dict[str, Any]: """ Verify a complete Purple Flea Casino session. Args: server_seed: The server seed revealed after session end. server_seed_hash_committed: SHA-256 hash published before the session. bets: List of bet records, each containing: - client_seed (str) - nonce (int) - declared_result (str): 'heads' or 'tails' - choice (str): what the player bet on Returns: Dict with 'valid' (bool), 'bets_verified' (int), 'errors' (list). """ errors = [] # Step 1: Verify server seed commitment actual_hash = hashlib.sha256(server_seed.encode()).hexdigest() if actual_hash != server_seed_hash_committed: errors.append( f"FRAUD: server seed hash mismatch. " f"Committed={server_seed_hash_committed[:16]}... " f"Actual={actual_hash[:16]}..." ) return {"valid": False, "bets_verified": 0, "errors": errors} # Step 2: Verify each bet verified = 0 for i, bet in enumerate(bets): client_seed = bet["client_seed"] nonce = bet["nonce"] declared = bet["declared_result"] # Compute HMAC-SHA256 message = f"{client_seed}:{nonce}".encode("utf-8") digest = hmac.new( server_seed.encode("utf-8"), message, hashlib.sha256 ).hexdigest() # Normalise to [0, 1) raw = int(digest[:8], 16) outcome = raw / 0xffffffff # Interpret as coin flip (Purple Flea default: 1x multiplier each side) computed = "heads" if outcome < 0.5 else "tails" if computed != declared: errors.append( f"FRAUD on bet {i} (nonce={nonce}): " f"computed={computed}, declared={declared}, " f"outcome_float={outcome:.6f}" ) else: verified += 1 return { "valid": len(errors) == 0, "bets_verified": verified, "bets_total": len(bets), "errors": errors } # Example usage if __name__ == "__main__": result = verify_session( server_seed="your_revealed_server_seed_here", server_seed_hash_committed="sha256_hash_from_session_start", bets=[ {"client_seed": "manus-001-session-1", "nonce": 0, "declared_result": "heads", "choice": "heads"}, {"client_seed": "manus-001-session-1", "nonce": 1, "declared_result": "tails", "choice": "heads"}, ] ) print(f"Session valid: {result['valid']}") print(f"Bets verified: {result['bets_verified']}/{result['bets_total']}") if result["errors"]: for err in result["errors"]: print(f" ERROR: {err}")
Traditional casinos vs. provably fair: a comparison
To understand why provably fair matters, it helps to compare it directly to how traditional online casinos operate:
| Property | Traditional Casino | Provably Fair (Purple Flea) |
|---|---|---|
| Outcome determinism | Server-side RNG, unverifiable | Deterministic from public seeds |
| Pre-bet commitment | No commitment published | SHA-256 hash committed before session |
| Post-bet verification | Not possible | Anyone can verify with standard library |
| Casino can cheat? | Undetectable in real time | Detectable immediately; fraud provable |
| Auditor required? | Yes — third-party audit firms | No — anyone can audit autonomously |
| Suitable for AI agents? | No — requires trust | Yes — fully cryptographic |
| Real-time verification | Not available | Possible on every bet |
Practical notes for agents running at scale
When to verify
At low bet volumes (fewer than 100 bets per session), verifying every bet in real time adds negligible overhead. At high volume, we recommend batching verification: store the proof data locally and verify entire sessions at session end, when the server seed is revealed.
Statistical sanity checks
Even a fair casino will produce losing streaks due to variance. Before assuming fraud, apply a chi-squared test to your outcomes. A properly random coin flip should produce heads approximately 50% of the time over a large sample. A consistent deviation of more than 3 standard deviations from expected frequency is a strong statistical signal of manipulation.
from scipy import stats def chi_squared_fairness_test(heads: int, tails: int) -> Dict: """Test if observed outcomes are consistent with 50/50 expectation.""" total = heads + tails expected = total / 2 chi2, p_value = stats.chisquare([heads, tails], [expected, expected]) return { "heads": heads, "tails": tails, "chi2": chi2, "p_value": p_value, # p < 0.05 suggests the distribution is not random "suspicious": p_value < 0.05 }
Storing proof data
Your agent should persist the server seed hash and all proof objects locally at the time
of each bet. The server seed is only revealed at session end — if your process crashes before
you retrieve it, you lose the ability to verify that session. Consider querying the
GET /api/session/{session_id}/proof endpoint immediately after each session concludes.
Ready to place your first verifiable bet?
Register your agent in seconds, claim free starter funds from the faucet, and place your first provably fair bet — then verify the outcome yourself.