{"data":{"kind":"file","path":"README.md","version_id":"ktmu2a0a8s7zrpy6nmphen9q","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":3393,"modified_at":"2026-07-05T18:59:40.861000","content_hash":"55257989db2f9ccbbf83f98b647742b2cd552c08007adf72eb8991542ed8fb43"},"entries":[],"content":"# Bodega — state-verified rewards for browser shopping agents\n\nBodega is a browser-use RL environment where agents shop on a store **we own**, so\nrewards come from **backend state the agent actually mutated** — checked via a\nprivate API against our database — not from an LLM judge reading a transcript.\nThis makes rewards near-unhackable for state-mutating tasks and produces a clean\ntraining signal.\n\n## Why state verification\n\nEvery shopping/browser env on the Hub is either read-only navigation scored by an\nLLM judge or a shopping eval without verifiable rewards. Bodega's differentiator:\nfor cart/checkout tasks, the reward is computed from the store's own database\n(`GET /api/verify/{sid}`, bearer-authed), so \"did the agent really add 2 blue\njackets?\" is answered by ground truth, not opinion.\n\n## Task tiers\n\n| Tier | Task | max_turns | Reward |\n|---|---|---|---|\n| T1 | Lookup (price / rating / spec / stock) | 5 | answer match |\n| T2 | Search + filter superlative | 8 | answer match |\n| T3 | Numeric comparison | 8 | answer match |\n| T4 | Cart build (exact multiset; supersets fail) | 10 | verify state |\n| T5 | Constrained cart (cheaper scores higher) | 14 | verify state (shaped) |\n| T6 | Checkout (items + coupon + shipping exact) | 16 | verify state |\n\nTasks are procedurally generated with machine-checked rejection rules (unique\nanswers, ambiguity margins, in-stock variants) and split into disjoint sets with\nan automated dedup check.\n\n**Split policy (public dev / private held-out, Zapier-style):**\n\n| Split | Shipped in package? | Purpose |\n|---|---|---|\n| `train-pool` | yes (public) | training pool |\n| `eval` | yes (public) | public dev/eval set |\n| `test` | no (repo only) | held-out, same distribution — official/uncontaminated numbers |\n| `eval-ood` | no (repo only) | held-out, different catalog — OOD generalization |\n\nOnly the public splits are bundled into the published environment, so the\nheld-out sets can never leak through the Hub. Official scores are measured\nlocally against `test` / `eval-ood`.\n\n## Usage\n\n```python\nimport verifiers as vf\nenv = vf.load_environment(\n    \"bodega\",\n    tier=\"t1,t2,t3\",      # \"t1\"..\"t6\" | \"all\" | comma list\n    split=\"eval\",          # public: \"train-pool\" | \"eval\"  (held-out, repo only: \"test\" | \"eval-ood\")\n    mode=\"dom\",            # \"dom\" (default, text model) | \"cua\" (vision fallback)\n    num_examples=-1,\n)\n```\n\n### Required environment variables\n\n| Variable | Used for |\n|---|---|\n| `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` | browser provider |\n| `MODEL_API_KEY` | Stagehand DOM executor (pinned `openai/gpt-4o-mini`) |\n| `BODEGA_VERIFY_KEY` | bearer for the store's session + verify API |\n| `BODEGA_STORE_URL` | store base URL |\n\n## Design guarantees\n\n- **Infra faults raise, never score 0.0** (D6): dead sessions / 5xx / expired-sid\n  404 raise `vf.Error` so prime-rl drops the rollout instead of poisoning the\n  gradient with a fake policy failure.\n- **Deterministic rewards** — no LLM judge anywhere.\n- **Pinned Stagehand executor** (`openai/gpt-4o-mini`) — recorded per run; an\n  executor change is treated as an environment change.\n- **Anti-hacking**: superset carts fail, multiple orders fail, zero-tool-call\n  rollouts score 0, answers can't be satisfied by echoing the prompt.\n\n## License / provenance\n\nStorefront catalog is fully synthetic (seeded generation) — no scraped data.\n","encoding":"utf-8","truncated":false,"total_bytes":3393},"status":null}