Run benchmarks for real and record agent-environment transitions as OTel GenAI JSONL.
Project description
environment-capture
Run agent benchmarks for real and record every agent-environment transition — each
(action → observation) pair, exactly as the environment returned it — as OpenTelemetry GenAI
JSONL. Integrating a benchmark is one small adapter; ten are already in (5,900+ real
trajectories / 27,000+ real transitions captured and published as license-tagged datasets on
the Hugging Face Hub).
Why
Because it's annoying to:
- set up benchmarks and run models against them — one three-method interface for any benchmark, any agent, any provider
- capture traces in a standardized format — every
(action → observation)transition as OTel GenAI JSONL, agnostic to benchmark and provider
Adding a benchmark? Point your coding agent at INTEGRATION.md — it's the complete, self-contained playbook for integrating one.
The benchmarks
| benchmark | environment | traces / transitions |
|---|---|---|
| bird-sql | text-to-SQL over real SQLite databases | 1,993 / 4,168 |
| financebench | financial-document QA over SEC-filing evidence | 1,254 / 7,402 |
| tau-bench | customer-service tool agents (airline/retail/telecom) | 1,033 / 5,289 |
| dabstep | pandas data analysis over a payments dataset + rules manual | 687 / 4,859 |
| continual-learning | exploration of a large obfuscated product database | 286 / 2,071 |
| terminal-tasks | computer-use agents in real terminal containers | 280 / 685 |
| swe-bench | software engineering in per-instance Docker images | 255 / 1,700 |
| crmarena | CRM analytics over a realistic Salesforce org | 80 / 553 |
| gaia2 | stateful multi-app simulated world (Meta ARE) | 37 / 563 |
| appworld | stateful multi-app simulated world | local-only (license) |
All published bundles include the trace corpus plus the task data needed to run the benchmark (task index, gold sidecars, evidence/context files).
Install
pip install environment-capture # the library: contract, capture driver, hygiene, hub fetch
pip install 'environment-capture[fetch]' # + huggingface_hub, for publishing bundles
Pure-package usage — capture YOUR benchmark and pull OUR data, no repo checkout needed:
from pathlib import Path
from environment_capture import run_capture, trajectory_to_spans, write_spans_jsonl
from environment_capture.hub import fetch_corpus
# 1) pull a published bundle (lands in ./environment-capture-data/, or $ENVCAP_DATA_ROOT)
corpus = fetch_corpus("bird-sql")
# 2) capture your own benchmark: implement the 3-method adapter + an agent, then
result = run_capture(my_adapter, my_agent, split="train")
spans = [s for t in result.trajectories for s in trajectory_to_spans(t, benchmark="my-bench")]
write_spans_jsonl(spans, Path("traces.otel.jsonl"))
The wheel ships the library and every benchmark adapter; benchmark data always comes from the
Hub (or your own capture runs). Note: hub publishing is currently pinned to the
experiential-labs org manifest — pushing your own benchmark's bundle means adding a
CorpusSpec (see INTEGRATION.md).
The contract
from environment_capture import (
BenchmarkAdapter, # tasks(split) / open_env(task) / grade(task, submission)
CommandEnv, # execute(command) -> ExecResult(output, returncode); close()
run_capture, # drive an agent over a split against the REAL env -> [Trajectory]
trajectory_to_spans, write_spans_jsonl, # Trajectory -> OTel GenAI JSONL
)
CommandEnv.executeis the substitution seam. A real adapter executes commands in a real workspace; swap in any other implementation (a simulator, a learned environment model) and the identical agent loop runs against it, graded by the same deterministic function.- Graders are deterministic.
grade(task, submission) -> floatmust not call an LLM. - Observations are never synthesized. A corpus comes from
run_captureagainst the real environment (or a conversion of someone else's REAL runs, with provenance).
Getting the data
# pull a full bundle (corpus + task data); local-first — never clobbers existing files
python -m environment_capture.hub fetch dabstep
python -m environment_capture.hub fetch all --force # explicit overwrite
# or straight from the Hub with no dependencies at all
curl -LO https://huggingface.co/datasets/experiential-labs/wmh-dabstep-traces/resolve/main/traces.otel.jsonl
Fetching is plain-HTTP stdlib: no extra dependency, no token for public repos, per-chunk
progress callbacks for UIs, atomic .part writes, file-level resume. Private repos work with a
token (HF_TOKEN or the stored hf auth login).
Publishing / updating corpora
python -m environment_capture.hub_push bird-sql # create or update (Hub keeps history)
python -m environment_capture.hub_push all --private # private repos
python <benchmark>/capture.py ... --push-hub # push straight from a capture wave
Pushing needs the fetch extra (environment-capture[fetch]) and a write token. Every push is
a Hub commit; re-pushing after new capture waves is the update path. Corpora are local-first:
nothing here ever deletes a local file.
Layout
environment-capture/
environment_capture/ # the package: contract + emitter + hygiene + hub (+ inline *_test.py)
<benchmark>/ # one dir per benchmark: adapter data, provenance README,
# thin capture/convert scripts; traces + task data are
# Hub-hosted and gitignored here
Adding a benchmark
Agents: follow INTEGRATION.md — it is the complete, self-contained playbook. Summary:
- Implement a
BenchmarkAdapterinenvironment_capture/benchmarks/<name>.py— fresh code against the benchmark's real upstream dataset (tests inline). - Create
<name>/with the task data (license-checked) and a capture or conversion script that writestraces.otel.jsonl. - Audit hygiene (
scan_spans_jsonl == {}), verify unique trace ids, eyeball trajectories, then publish the bundle withhub_push.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file environment_capture-0.1.0.tar.gz.
File metadata
- Download URL: environment_capture-0.1.0.tar.gz
- Upload date:
- Size: 76.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6eb638c7b20ff80af7062a305063baab204c6aa510e49e2de901529763fea094
|
|
| MD5 |
d6d5e129ef5141c555809fb6dae07ead
|
|
| BLAKE2b-256 |
3e8b03df69f1aa8187066e9665374d5b377c87f06b2a2110ec6f6b950dfdc476
|
File details
Details for the file environment_capture-0.1.0-py3-none-any.whl.
File metadata
- Download URL: environment_capture-0.1.0-py3-none-any.whl
- Upload date:
- Size: 99.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f21614efd8c5a26eff29aebc5436e46a0463d42813252a93dca6b7dcb698516
|
|
| MD5 |
d259d3377dff5e942e03a0def5f7165a
|
|
| BLAKE2b-256 |
4a46407618f5a6cf83d61cec57a3016aa308d63f3afecb9c6f2da01d9636d177
|