CoolFace
Datasetpublic

sergiopaniego/opencode-rollout-trace

One opencode rollout, as the trainer sees it The artefact behind the talk Training a coding agent through a harness you did not write (Lisbon AI, September 2026). An off-the-shelf coding agent, opencode, runs untouched in a remote sandbox. A proxy sits between it and vLLM, speaks the agent's own dialect, and records every model call the agent makes together with the exact token ids and logprobs. That recording is what gets trained on. This repo is one of those recordings, plus… See the full description on the dataset page: https://huggingface.co/datasets/sergiopaniego/opencode-rollout-trace.

sourceHugging Faceapache-2.0updated 16h agoView on Hugging Face
0likes188downloads
Dataset Card

One opencode rollout, as the trainer sees it

The artefact behind the talk Training a coding agent through a harness you did not write (Lisbon AI, September 2026).

An off-the-shelf coding agent, opencode, runs untouched in a remote sandbox. A proxy sits between it and vLLM, speaks the agent's own dialect, and records every model call the agent makes together with the exact token ids and logprobs. That recording is what gets trained on. This repo is one of those recordings, plus the code that produced it.

Nothing here is a transcript. A transcript would be text, and retokenising text gives you different ids than the ones the model actually sampled. That difference is the point.

Files

FileWhat it is
trace.jsonthe raw proxy trace: every captured model call, in order, as recorded
turns.jsonthe real agent turns, derived exactly as training derives them (see below)
task.jsonthe instruction the agent was given, and its task id
visible_tests.txtthe example cases the agent could see, from the problem statement
held_out_tests.jsonthe tests that produce the reward, which the agent never sees
summary.jsonreward, turn counts, tool counts, and how many turns training keeps
capture_trace.pydrives one session and writes all of the above
capture_launcher.pyserves vLLM, opens a tunnel, runs the capture, as one HF Job

Reading turns.json

Each turn carries what the training path actually uses:

  • prompt_ids: the conversation sent to the model that turn, re-tokenized with its tools, so the prompt matches what the upstream rendered
  • output_ids: the ids the model generated, taken from the capture and not re-encoded
  • per_token_logps: the generator's logprobs for those ids
  • trained: whether the training policy keeps this turn. Here it is has_tool_call, so turns where the model took an action are kept and pure-text turns are not
  • mask: derived, not recorded. 0 for the context, 1 for the tokens the model generated. The proxy never stores a mask, the distinction is structural: only output_ids get a gradient. It is materialised here because that distinction is the whole reason the artefact is interesting.

Turn count in turns.json is smaller than in trace.json on purpose. opencode fires extra model calls for its own bookkeeping, a title generator and a context summariser, and those are not the task. Training them with the rollout's reward would reinforce the wrong thing, so they are filtered by anchoring on the system prompt of the first tool-enabled turn.

Reproducing it

sh
TASK_INDEX=0 PUSH_TO_DATASET=sergiopaniego/opencode-rollout-trace \
hf jobs uv run --flavor a100-large --secrets HF_TOKEN --timeout 3600s \
  "https://huggingface.co/datasets/sergiopaniego/opencode-rollout-trace/resolve/main/capture_launcher.py"

One GPU is enough: this captures, it does not train, so there is no weight sync. The vLLM flags matter, --return-tokens-as-token-ids is what lets the proxy recover exact ids instead of re-encoding decoded text.

build_dataset(n_prompts, seed) in the training example is deterministic, so TASK_INDEX selects a reproducible task. Keep N_PROMPTS equal to what the training run used and the indices line up.

Where this comes from