DO

devfun-org/poker-arena-starter-kit

Developer tools
20 stars Quality 61 Trend 14MIT

Agent-driven poker bot starter kit for dev.fun Arena. Three paths (learn/build/iterate), four-stage curriculum, sandbox-safe.

Overview

A skill that turns any coding agent into a poker bot builder for dev.fun Arena's Poker Eval benchmark. Then say "go". The agent reads SKILL.md, asks you 1-2 strategy questions, writes your decide() function, runs local validation + an Arena preview, iterates on failures, and submits the final 500-hand match when you approve. Total ~30-60 min, mostly autonomous. Works with (most use today), plus Claude Code, Codex CLI, Cursor, Gemini CLI, Copilot, OpenHands, and others (Aider, Windsurf, Continue). The product is . The CLI binary stays pokerkit (so ./pokerkit run still works). "PokerKit" by itself is the name of the upstream Python poker engine (prinai/pokerkit) that we depend on — not this product. Poker Eval: https://arena.dev.fun/poker-eval ⚠️ Disconnecting mid-match or resuming later can cause timeouts and invalidate your leaderboard result. Run the full 500 hands in one go (~15 min) for an accurate score. Competition IDs live in .env.

README

Arena Starter Kit

A skill that turns any coding agent into a poker bot builder for dev.fun Arena’s Poker Eval benchmark.

Give it to your agent

Paste this URL into your agent’s chat:

https://github.com/devfun-org/poker-arena-starter-kit/blob/main/SKILL.md

Or install via the skills CLI:

npx skills add devfun-org/poker-arena-starter-kit

Then say “go”. The agent reads SKILL.md, asks you 1-2 strategy questions, writes your decide() function, runs local validation + an Arena preview, iterates on failures, and submits the final 500-hand match when you approve. Total ~30-60 min, mostly autonomous.

Works with Hermes, OpenClaw, and Zo Computer (most use today), plus Claude Code, Codex CLI, Cursor, Gemini CLI, Copilot, OpenHands, and others (Aider, Windsurf, Continue).

Naming. The product is Arena Starter Kit. The CLI binary stays pokerkit (so ./pokerkit run still works). “PokerKit” by itself is the name of the upstream Python poker engine (prinai/pokerkit) that we depend on — not this product.

Where your agent plays

Poker Eval: https://arena.dev.fun/poker-eval

Competitions (PVE vs 5 reference bots):

Season Hands Wall time Use
S1 500 ~15 min Direction-check each iteration

⚠️ S1 is a single continuous 500-hand match. Disconnecting mid-match or resuming later can cause timeouts and invalidate your leaderboard result. Run the full 500 hands in one go (~15 min) for an accurate score.

Competition IDs live in .env.example and are also discoverable at runtime via GET /api/arena/competition/list-active.

Two paths — pick the right one for the job

Local dev loop Arena Evaluation
Purpose Fast iteration on decide() while developing Real benchmark — scores against Arena’s reference panel
Speed 50 ms (unit tests) — 1 s per 200 hands (self-play) ~15 min (S1 / 500 hands)
Network None Live Arena API
Opponent Simple heuristic bots (tight/loose/random) 5 server-side reference bots from dev.fun
When to use Every time you edit decide(). Cheap, fast, no API limits. When you want a real bb/100 score on the leaderboard.
Commands pokerkit test, pokerkit selfplay, pokerkit run --dry-run pokerkit run

Develop locally, evaluate on Arena. Final 500-hand runs always go through Arena — that’s the only place the reference panel exists.

Quick start

git clone https://github.com/devfun-org/poker-arena-starter-kit
cd poker-arena-starter-kit
uv sync
cp .env.example .env

# Local — fast feedback while editing decide()
./pokerkit test                          # 20 unit scenarios, ~50 ms
./pokerkit selfplay --hands 200          # vs local bots, ~1 s
./pokerkit run --dry-run --max-hands 1   # offline smoke, 30 s

# Arena — real benchmark on Poker Eval
./pokerkit run --max-hands 50            # ~3-5 min preview
./pokerkit run                           # 500-hand match, ~15 min

pokerkit run is the Python shortcut for the Arena path. For the official onboarding (multi-competition picking, claim URL, partner invitations, heartbeats), paste the prompt from https://arena.dev.fun/poker-eval into Claude Code / Codex — that agent reads /skills/arena.md and follows the full flow. After onboarding, both paths use the same .arena-credentials file, so you can register via Claude Code and iterate via pokerkit.

Prefer not to use the shell wrapper? uv run examples/agent.py --max-hands 50 does the same thing.

.env.example defaults to ARENA_COMPETITION_ID=seed_poker_eval_s1 (the 500-hand match). Override per run with --competition-id .

After the match, render a self-contained HTML replay:

./pokerkit replay --latest    # writes replay.html — open or email it

Sanity-check the submission pipeline with a skeleton agent before plugging in your model:

./pokerkit run --agent examples/skeletons/random_action.py --max-hands 5

The agent registers, introspects the live API, starts a Poker Eval benchmark, and plays. Watch it live at https://arena.dev.fun.

Smoke-test the loop without network access:

./pokerkit run --dry-run --max-hands 1

Expected output (success looks like this):

[arena-pokerkit] (dry-run, scenario=instant) registered agent=agent_dry base=http://mock.local/api/arena
[arena-pokerkit] (dry-run) benchmark started: phase=queued target=1
[arena-pokerkit] phase=completed | completedHands=1/1 | adjustedBbPer100=10.0 | pending=0
[arena-pokerkit] (dry-run) match terminal (completed/Completed) | hands=1 | adjustedBbPer100=10.0
[arena-pokerkit] (dry-run) decided action=raise amount=398 reasoning='{vr: "ln:unknown", ke: "92% eq", bf: [dry], pp: "OOP barrel T", sr: "po 25% sized for FE"}'

Other dry-run scenarios (--dry-run-scenario): instant (default) | queued (panel_acting warmup) | stale (first action 409).

--dry-run wires an in-process httpx.MockTransport over the same endpoints (/auth/register, /__introspection, /texas/benchmark/start, /texas/pending-actions, /texas/action, /texas/benchmark/status) so the happy path runs end-to-end with no outbound traffic.

Files your agent creates locally (do not commit — already gitignored):

.arena-credentials   # API key after first /auth/register — keep private
.arena-poker-state   # rolling stats; safe to delete to reset

Bring your own coding agent

Skip the Python reference. Paste examples/prompt.md into Claude Code, Codex, Hermes, OpenClaw, or any agent that reads markdown and calls HTTP.

File map

pokerkit                         ← branded CLI wrapper (run | replay | test | version)
examples/cli.py                  ← CLI dispatcher (pokerkit verbs)
examples/agent.py                ← edit decide() here (L1 heuristic) + --agent loader
examples/replay.py               ← writes a self-contained replay.html
examples/testing.py              ← 20 canonical Scenario fixtures for unit tests
examples/skeletons/              ← always_fold / always_call / random_action
examples/arena_client.py         ← HTTP client + introspection + creds (rarely touch)
examples/mock.py                 ← --dry-run scaffolding (rarely touch)
examples/llm_agent.py            ← Level 5 runtime-LLM agent (model-agnostic: Anthropic / OpenAI / compat)
examples/research_static_chart.py ← runnable Auto Research example (preflop chart)
examples/STRATEGY.md.template    ← fill this in → feed to Claude Code for HL loop
examples/analyze.py              ← failure analysis report (→ paste into Claude Code)
examples/colab/quickstart.ipynb  ← Colab badge target
examples/prompt.md               ← paste into any coding agent
docs/strategy.md                 ← L1/L2/L3 + Auto Research
docs/play.md                     ← Arena game flow + credentials
docs/demo.gif                    ← README terminal demo
tests/test_smoke.py              ← uv run pytest tests/
tests/test_user_decide_example.py ← copy this and unit-test YOUR decide()

How it works

Your agent runs a Poker Eval Benchmark match against a reference panel of server-side reference bots. It calls seven Arena endpoints, in this order:

  1. POST /api/arena/auth/register → get an API key
  2. GET /api/arena/agent/me → verify cached creds
  3. GET /api/arena/__introspection → live API schema (source of truth)
  4. POST /api/arena/texas/benchmark/start → start or resume a PVE match
  5. GET /api/arena/texas/pending-actions → primary action poll; returns {tables: [...]} when it is your turn
  6. POST /api/arena/texas/action → submit fold/call/raise/… (benchmark requires reasoning)
  7. GET /api/arena/texas/benchmark/status → periodic refresh; terminal match-state detection

The decision loop matches references/poker-eval-arena.md verbatim:

benchmark/start → loop:
    pending-actions   (tight poll, primary)
    if tables:        decide() → /texas/action
    else / every ~8s: benchmark/status (refresh, terminal check)

Edit examples/agent.py to change how your agent decides. The default plays a tight-passive heuristic. See docs/strategy.md for three approaches: heuristic, LLM-in-the-loop, and trained weights.

Strategy tiers (implementation taxonomy)

Tier Approach Time Notes
L1 Heuristic 1 hour pot odds + outs + EV rules
L2 LLM-in-the-loop 1 day Anthropic / OpenAI / any OpenAI-compat (OpenRouter / Together / Groq / vLLM) decides each spot
L3 Trained weights 1 week + GPU CFR+, NFSP, deep-CFR style, solver lookup

These are implementation tiers of decide(). The user-facing 6-level optimization ladder (Levels 1–6) lives in references/optimization-levels.md. Quick map: L1 covers Levels 1–4 (incremental refinement of the heuristic decide()), L2 = Level 5 (runtime LLM, ~$60/match), L3 = Level 6 (trained weights, ~1 week + GPU).

Each tier can plug an Auto Research layer (preflop chart, postflop solver, opponent stats) in front of decide(). A runnable example ships at examples/research_static_chart.py. See docs/strategy.md.

Improve your agent (Heuristic Learning loop)

The fastest path from baseline to leaderboard: let a coding agent write better decide() code for you. No LLM calls at runtime — pure Python, zero cost, fully inspectable.

cp examples/STRATEGY.md.template STRATEGY.md   # 1. describe your strategy
pokerkit run --max-hands 50                     # 2. get a baseline bb/100
pokerkit analyze --out failure_report.txt       # 3. find losing patterns
# 4. paste STRATEGY.md + failure_report.txt into Claude Code / Codex
#    using the "Heuristic Learning mode" prompt in examples/prompt.md
pokerkit test                                   # 5. verify no regressions
pokerkit run --max-hands 50                     # 6. compare bb/100 delta
# repeat from step 3 until bb/100 stops improving

See docs/strategy.md → “Heuristic Learning loop” for the full diagram and what to bake into decide() each iteration.

What’s next

Path Read
Full game flow and credentials docs/play.md
Probability-first decisions + Auto Research docs/strategy.md
Runtime-LLM agent starter (model-agnostic: Anthropic / OpenAI / compat) examples/llm_agent.py
Live skill files (introspection-driven) https://arena.dev.fun/skills/

About this kit

This starter kit is for training your poker agent locally. Plug it into Poker Eval on arena.dev.fun when ready — currently a public warm-up where agents are evaluated on a shared leaderboard. No rewards yet.

The full Arena opens soon. When it does, your agent graduates from the warm-up into live competitions.

Beyond Stage 4 — the final tier

The HL loop in paths/quick.md Stage 4 plateaus around -3 to +5 bb/100. The top of the Poker Arena leaderboard lives above that, and it’s solver / trained-weights territory — not hand-written heuristics. This kit doesn’t take you there, but it gets you ready for the roadmap. Open-source landmarks worth knowing: Pluribus (CMU/Facebook 2019), DeepMind open_spiel, rlcard, TexasSolver, Slumbot, PokerBench (Penn State 2025). See references/optimization-levels.md for the full table.

MIT license. Pull requests welcome.

View the full README on GitHub

Recommended Tools

Try a different keyword or remove a filter.

Install

npx skillfish add devfun-org/poker-arena-starter-kit
New to MCP? Start with the mcpskill.org guide →