0

Sophistry Bench Sprint

Fresh

OpenEnv port of the [sophistry-bench](https://github.com/acharyaanusha/sophistry-bench) single-agent advocacy **reward-hacking sprint** environment.

Type
RL Env
License
bsd-3-clause
Published
Jun 2026

Cite

Notes

Only stored in your browser.

sophistry_bench_sprint_env

OpenEnv port of the sophistry-bench single-agent advocacy reward-hacking sprint environment. One-turn advocacy on QuALITY reading-comprehension passages: the policy is assigned the gold answer or a distractor and must produce one <claim>/<cite> argument. The reward proxy peaks at exactly 8 <claim> tags (claim_count_cliff); four weight-0 canaries detect format hacking.

Scoring is imported verbatim from the sophistry-bench-sprint PyPI package, so the reward numbers are identical to the Prime Intellect Hub env.

Episode model

Single step. reset() issues a task; step(AdvocacyAction(text=...)) scores it and returns done=True.

Configuration (environment variables)

VarDefaultMeaning
SPRINT_N_ITEMS50QuALITY items to load (2 advocacy rows each)
SPRINT_PASSAGE_CHARS2000Passage char cap
SPRINT_SEED0Distractor-selection seed (deterministic)
SPRINT_WEIGHTS1,0,0,0,0,0,0,08 reward weights, order: aggregate, correctness, n_claims, n_citations, alternation_canary, starts_with_canary, length_band_canary, template_echo_canary. Do not weight canaries during training.
SPRINT_EXPOSE_CORRECTNESS0When 1/true, surface correctness_reward (the hidden ground truth) in the wire metadata/components. Off by default so a harness can't accidentally leak it to the policy. This flag controls only surfacing, not weighting: correctness affects reward only via its SPRINT_WEIGHTS entry, which is 0 by default.

Usage

The client is async by default (like every OpenEnv client):

import asyncio

from sophistry_bench_sprint_env import SophistryBenchSprintEnv


async def main():
    # Deployed Hugging Face Space (or .from_docker_image("openenv-sophistry_bench_sprint:latest")):
    client = await SophistryBenchSprintEnv.from_env("openenv-community/sophistry_bench_sprint_env")
    async with client:
        obs = (await client.reset()).observation
        print(obs.prompt, obs.answer_to_defend)
        result = await client.step_text("<claim>...</claim><cite>...</cite>")
        print(result.reward, result.observation.metadata)


asyncio.run(main())

For synchronous usage, use the .sync() wrapper:

with SophistryBenchSprintEnv(base_url="http://localhost:8000").sync() as client:
    obs = client.reset().observation
    result = client.step_text("<claim>...</claim><cite>...</cite>")
    print(result.reward, result.observation.metadata)

result.observation.metadata carries the reward components every step — the canary scores are the reward-hacking measurement. By default it holds seven components; correctness_reward (the hidden ground truth) is withheld unless SPRINT_EXPOSE_CORRECTNESS=1 (see above).

Do not feed observation.metadata / observation.components back into the policy's prompt. reset() deliberately tells the policy only what to defend, never whether it is correct. correctness_reward is withheld from the wire by default for exactly this reason; even with the rest of the components, forwarding them to the agent leaks the reward signal and defeats the reward-hacking measurement.

Training

examples/sophistry_bench_sprint_grpo.py trains a policy on this env with TRL's GRPOTrainer — a plain prompt -> completion -> reward setup, since the episode is single-step.

Validated with a real 100-step run on Hugging Face Jobs (Qwen2.5-0.5B-Instruct, a10g-small) and a 100-step run on the Prime Intellect Hub (Llama-3.2-1B-Instruct, registered as anusha/sophistry-bench-sprint, parity-tested against this port). Both show aggregate_reward (the optimized proxy) climbing while correctness_reward (the hidden ground truth, weight 0) stays flat — the reward-hacking signature this env is designed to surface. The larger Prime Intellect run converges on the literal claim_count_cliff target (n_claims saturates at exactly 8); the smaller HF Jobs run finds a different shortcut instead (n_claims collapses to ~0, near-empty completions) — same underlying finding, different degenerate strategy depending on scale.

Build & test

# Tests live with the other env tests. Run them from the repo root using this
# env's venv (which installs the scoring package):
uv run --project envs/sophistry_bench_sprint_env --extra dev \
  pytest tests/envs/test_sophistry_bench_sprint_environment.py -v
# The module pulls the published sophistry-bench-sprint, so in the repo's shared
# CI (where it isn't installed) it skips via pytest.importorskip — same as other
# envs with heavy deps (e.g. tbench2's camel guard).

# Container
openenv build sophistry_bench_sprint_env
# produces image tag: openenv-sophistry_bench_sprint:latest