Tech Stack Deep Dive β What Each Tool Does and Its 2026 Frontier
Purpose: deep technical reconnaissance for the Meta PyTorch OpenEnv Hackathon finalist team. For each tool: what it is, what it does at each layer, 2026 frontier features, integration points, gotchas that break the LLM-screener gate, real APIs, and depth-of-help ceiling.
Executive summary β what's a differentiator, what's table stakes
Table stakes (every serious team has these):
- OpenEnv (you must submit an env)
- TRL GRPOTrainer (default training path)
- HF Spaces + Docker (deployment target)
- PyTorch, Python, Colab (substrate)
- W&B (logging)
Pitch differentiators (most teams won't use these at depth):
- TRL v1.2
environment_factorywith multi-env + per-env reward masking β released 2026-04-17, 2 days before the hackathon email. Almost nobody outside the HF core team has done multi-environment GRPO yet. - OpenEnv v0.2.2+ MCP native environments (
MCPEnvironment) β RFC 003, production+simulation modes, tool discovery through MCP JSON-RPC. Lets your env speak to any MCP server in the world. - RFC 004 Rubrics β LLM-as-judge rewards with delayed signals, baked into v0.2.2. Most teams will hand-write reward functions.
- Unsloth ultra-long-context RL (Jan 2026 update) β 380K ctx gpt-oss on a single B200, 110K on an H100. If your env benefits from long horizons, this is your moat.
- RFC 005 agentic harness integration β makes your env callable from Claude Code / OpenClaw directly. Zero teams will ship this.
- TRL v1.1 AsyncGRPOTrainer + chunked LM head β 44Γ lower peak memory on 8K seq. Unlocks bigger models on Colab.
- Torchforge Services model (
.route(),.fanout(),.session()adverbs on Monarch actors) β sticky-session KV cache reuse is brand new. - TRL v1.2 SSDTrainer (self-distillation, no reward model) β self-improvement loop with no verifier needed.
Tool 1: OpenEnv (meta-pytorch/OpenEnv)
Elevator: A Gymnasium-style interface library + server runtime for defining isolated, reproducible RL environments that agents/LLMs train against; current v0.2.3 (Mar 28 2026).
What it does at each layer
- Contract layer: Defines typed
Action,Observation,State,StepResultPydantic models per environment. Standardizesreset()/step(action)/state(). - Server runtime: Wraps your env in a FastAPI app (
create_app(...)) inside a Docker container, exposed over HTTP + WebSocket. Handles concurrency, session IDs,/webUI,/health. - Client runtime: Auto-generated Python client (
MyEnv(base_url=...)). Async-first (async with EchoEnv(...) as client:) with sync wrappers. - Publishing layer: Bundles env as a Hugging Face Space (Docker SDK), pip-installable via
git+https://huggingface.co/spaces/<org>/<env>. - Catalog layer: HF collection
openenv/openenv-environment-hub, discoverable by short name or repo ID.
Latest features (Q4 2025 β Q1 2026)
- v0.2.1 (Feb 4 2026): First MCP support lands (FastMCP integration). TDD workflow with git hooks and skills. RFC 004 rubrics introduced.
- v0.2.2 (Mar 20 2026 β THE BIG ONE):
- MCPEnvironment with tool discovery (
ListToolsAction), tool-call execution (CallToolAction), FastMCP 2.x/3.x compatibility, reserved-name validation, persistent MCP sessions, production vs simulation modes, code mode support. - Async-first clients with persistent WebSocket sessions + sync wrappers.
- Rubric/evaluation support with delayed rewards and LLM-based scoring (RFC 004).
- Auto-discovery API β load env by short name or Hub repo ID (
load_env("echo")). - Built-in web UI at
/webwith dynamic forms, action history, live state. - Creator CLI (
openenv init,build,validate,push,fork,serve,skills). - One-command HF publishing + fork/duplicate for Spaces + custom registry push.
- GenericEnvClient / GenericAction β raw-dict access without installing env-specific code (great for testing unknown envs).
- MCPEnvironment with tool discovery (
- v0.2.3 (Mar 28 2026 β polish release):
GET /+GET /webredirect to/web/for Gradio-backed Spaces.GET /web/statereturns 409 before reset (instead of 500).POST /web/resetaccepts optional reset kwargs.- Shared
gradio_webprobe,repl_webexpanded for root-path validation. - Canonical collection discovery defaults to first-party unsuffixed Spaces.
- REPL-specific Gradio control panel retained + server compat fixes for Hub.
Killer integration points
- β TRL:
GRPOTrainer(environment_factory=MyEnv)β TRL importsopenenv-core>=0.2.1implicitly. Works over WebSocket to your Space. - β HF Spaces:
openenv pushone-shot publishes; Space provides the Docker runtime AND the web UI AND the pip install path. - β MCP (RFC 003): Wrap any MCP server as an env; or expose env actions as MCP tool calls (RFC 004).
- β smolagents:
coding_envuses smolagents sandbox under the hood for persistent-context Python execution. - β Claude Code / OpenClaw (RFC 005): agentic-harness integration β your env becomes a skill any harness can call.
Gotchas that break the LLM screener
- Concurrency trap: default
max_concurrent_envs=1. TRL opens N WebSockets (one per generation). MUST setSUPPORTS_CONCURRENT_SESSIONS = Trueandcreate_app(..., max_concurrent_envs>=generation_batch_size)or training hangs and the screener will see no reward signal. - Platform flag:
docker run --platform linux/amd64 ...is mandatory on Apple Silicon. Without it the Space image fails to run on a judge's Mac. - Duplicate the Space for training: shared community Spaces throttle to 1 session β training will appear to "work" for 1 episode then silently stall.
- Port collision: map Space port 8000 β host 8001 so vLLM can keep 8000.
- Docstring-driven tool schema: tool methods MUST have
Args:-style docstrings with typed params or TRL generates a broken tool schema and the model never calls them. (Screener sees 0 reward.) reset()signature: must accept**kwargsβ TRL forwards dataset columns into it. Not doing this crashes on first batch.__init__no-args rule: TRL callsMyEnv()with zero args. Configure via module-level vars or env vars, not constructor args.
Specific APIs / commands
# Core env author code
from openenv import Action, Observation, Environment, create_app
@dataclass
class MyAction(Action):
move: str
@dataclass
class MyObservation(Observation):
board: list[list[str]]
reward: float
done: bool
class MyEnv(Environment):
SUPPORTS_CONCURRENT_SESSIONS: bool = True
def reset(self, **kwargs) -> MyObservation: ...
def step(self, action: MyAction) -> StepResult[MyObservation]: ...
app = create_app(MyEnv, MyAction, MyObservation, max_concurrent_envs=64)
# CLI
openenv init my_env
openenv validate # run contract checks
openenv build # docker build
openenv serve --port 8000 # local run
openenv push --repo-id me/my_env # HF Space deploy
openenv fork openenv/echo_env # duplicate existing env
# Docker deploy
docker run -d -p 8001:8000 --platform linux/amd64 registry.hf.space/<org>-<env>:latest
# MCP environment (RFC 003)
from openenv.mcp import MCPEnvironment, ListToolsAction, CallToolAction
env = MCPEnvironment(mcp_server_urls=["http://localhost:3333"])
tools = env.step(ListToolsAction()) # discovers tools
result = env.step(CallToolAction(tool_name="search",
parameters={"q": "..."}))
Depth-of-help ceiling
OpenEnv takes you all the way from env definition β containerized deployment β HF Space β pip-installable artifact. It does not do: reward shaping (that's your code), training (TRL's job), or evaluation harnesses beyond rubrics (you wire those yourself). Hard ceiling: single-process-per-episode. If you need true multi-agent concurrent interaction (not just parallel rollouts), you hand-roll on top.
Tool 2: HF TRL β Transformers Reinforcement Learning
Elevator: HuggingFace's RL post-training library; the canonical place where GRPO, DPO, KTO, PPO live. v1.2.0 (Apr 17 2026) landed 2 days before the hackathon email.
What it does at each layer
- Algorithm layer: Implementations of GRPO, DPO, KTO, PPO, GSPO, SFT, DPPO, VESPO, SDPO, SSDTrainer (v1.2 self-distillation, no reward model), DistillationTrainer.
- Rollout layer: Handles multi-turn generation via vLLM (colocate or server mode), tool-call parsing, environment stepping.
- Reward layer: Reward functions are plain Python callables receiving
environmentskwarg. - Logging layer: Native W&B / TensorBoard / MLflow via
report_to. - Env layer:
environment_factory(recommended) orrollout_func(escape hatch).
Latest features (v1.0 β v1.2 diff)
- v1.0.0 (Mar 31 2026):
- AsyncGRPOTrainer β decouples generation from gradient updates via external vLLM server.
- VESPO (variational sequence-level soft PO) β addresses training instability with smooth asymmetric Gamma weighting.
- DPPO (divergence-based PPO clipping).
- SDPO (self-distillation using model's high-reward trajectories as teacher).
- Reward functions can return extra diagnostic columns via
log_extra/log_metric. - 35% faster packing (BFD strategy,
"bfd_split"). - v0βv1 migration guide published.
- v1.1.0 (Apr 12 2026):
- DistillationTrainer β on-policy knowledge distillation with generation buffers (up to 40Γ speedup), external teacher support, binary-encoded logprobs (~5Γ payload reduction).
- AsyncGRPOTrainer chunked LM-head computation β 44Γ lower peak memory on 8192-token sequence.
- SFTTrainer auto-patches chat templates missing
{% generation %}markers. - Tool-calling expanded: GPT-OSS, GLM-4-MoE, Qwen3-VL, Gemma 4.
- VLM training end-to-end with images in tool responses.
- v1.2.0 (Apr 17 2026 β HACKATHON RELEASE):
- SSDTrainer β self-distillation without reward models (samples at training-time temp, fine-tunes on unverified samples).
- GRPOTrainer: tool results now use rollback instead of truncation when exceeding
max_completion_length(eliminates ~80 lines of image-boundary bookkeeping). - Tool-calling: Llama 3.1/3.2 + DeepSeek-V3 templates.
- KTO/DPO alignment cleanup.
Killer integration points
- β OpenEnv:
environment_factory=MyEnvClassβ the one-line integration. TRL discovers tool methods from docstrings. - β vLLM:
use_vllm=True, vllm_mode="colocate"(1-GPU Colab) or"server"(2+ GPU). Colocate shares GPU memory between inference + train. - β W&B:
GRPOConfig(report_to="wandb", log_completions=True)β logs completions as rich HTML tables. - β Unsloth: Unsloth monkey-patches TRL's GRPOTrainer; you write TRL code and get Unsloth speedups transparently.
- β HF Hub:
push_to_hub=Trueuploads trained LoRA/full checkpoint as a Model repo. - β HF Jobs (new v0.27+):
uv run examples/scripts/openenv/echo.py+hf jobsruns training in HF cloud.
Gotchas that break the LLM screener
transformers>=5.2.0requirement forenvironment_factoryβ main branch install. Pinning to older transformers silently disables the factory path.environment_factoryis marked experimental β its exact signature may change; pin TRL to1.2.0exactly.- Pass the CLASS not an instance:
environment_factory=MyEnvClass(no parens). PassingMyEnvClass()will break multi-rollout parallelism. max_completion_lengthis TOTAL tokens across all turns, not per-turn. Default 256β1024 will cut off multi-turn episodes mid-game β bump to 4096 minimum for anything non-trivial.- Tool method discovery is reflection-based: any public method (no leading
_) becomes a tool. A straydef helper(self)becomes an advertised tool and confuses the model. - Reward metric logging ignores
reward_weights(open issue #5352 as of Mar 2026) β the displayed reward is unweighted sum even though training uses weights. Don't panic if W&B chart looks off. num_generationsmust divideper_device_train_batch_size Γ gradient_accumulation_stepsor GRPO crashes with an obscure assert.
Specific APIs
from trl import GRPOTrainer, GRPOConfig
trainer = GRPOTrainer(
model="Qwen/Qwen3-1.7B",
reward_funcs=[reward_func], # can be list of funcs
train_dataset=dataset,
args=GRPOConfig(
use_vllm=True,
vllm_mode="colocate", # or "server"
num_generations=4,
gradient_accumulation_steps=64,
max_completion_length=4096,
chat_template_kwargs={"enable_thinking": False},
log_completions=True,
report_to="wandb",
loss_type="gspo", # or "grpo" or "dr_grpo"
epsilon=0.2,
epsilon_high=0.28, # one-sided clipping
delta=1.5, # two-sided clipping
mask_truncated_completions=True,
),
environment_factory=MyEnvClass, # THE factory β CLASS, not instance
)
trainer.train()
trainer.push_to_hub("my-team/grpo-wordle-qwen3-1.7b")
# vLLM server mode (2+ GPU)
CUDA_VISIBLE_DEVICES=0 trl vllm-serve --model Qwen/Qwen3-1.7B --host 0.0.0.0 --port 8000
CUDA_VISIBLE_DEVICES=1 python train.py --vllm-mode server --vllm-server-url http://localhost:8000
# HF Jobs
uv run examples/scripts/openenv/wordle.py
Depth-of-help ceiling
TRL owns the entire training pipeline from prompts β trained model. It does not own: memory optimization (Unsloth), env definition (OpenEnv), distributed-scale scheduling (Torchforge/accelerate). On a Colab T4 you'll hit OOM on any model >3B without Unsloth.
Tool 3: Unsloth
Elevator: A drop-in speed+memory optimizer for HF transformers that enables LoRA/QLoRA GRPO on consumer GPUs, with 5β8Γ memory reduction and 2β3Γ speedups.
What it does at each layer
- Kernel layer: Triton kernels for LM head, attention, MLP, layer norm.
torch.compileintegration yields 8Γ smaller memory for linear kernels. - Model loader layer:
FastLanguageModel.from_pretrained(..., load_in_4bit=True, fast_inference=True)β patches HF model with Unsloth kernels in-place. - Training adapter: Monkey-patches TRL's GRPOTrainer so you write TRL code and get Unsloth's perf transparently.
- vLLM shared memory: Unsloth eliminates the 5GB double-alloc overhead when vLLM and training both hold weights.
Latest features (Q4 2025 β Q1 2026)
- Jan 15 2026 update β Ultra-long context RL:
- gpt-oss QLoRA at 380K context on a single 192GB B200.
- Qwen3-8B GRPO at 110K context on an 80GB H100.
- New batching algorithms β 7Γ longer context (often 12Γ) with no accuracy or speed regression.
- gpt-oss RL support: 3Γ faster inference, 50% less VRAM, 8Γ longer context for gpt-oss specifically.
- Qwen3-VL-8B GSPO/GRPO on free Colab T4 β the "vision-RL-on-Colab" flex.
- GSPO (Group Sequence PO) β Alibaba Qwen's sequence-level variant. Set
loss_type='gspo'. - Vision RL (VLM RL) guide for multimodal tasks.
- DPO/ORPO/KTO preference optimization also supported.
Killer integration points
- β TRL:
from unsloth import FastLanguageModelbeforefrom trl import ...β patches TRL silently. - β vLLM:
fast_inference=Trueenables shared weight memory between vLLM (for GRPO rollouts) and training. - β HF Hub:
model.push_to_hub_merged(...)β pushes LoRA merged into the base checkpoint. - β Colab: Unsloth's notebooks are literally designed to fit on a free T4 (16GB). This is where 95% of hackathon submissions will train.
Gotchas
- Import order matters:
from unsloth import FastLanguageModelMUST come before any transformers/trl imports or patching fails silently. fast_inference=Trueis vLLM-dependent β only for vLLM-supported models. If unsupported, setFalseor model loader crashes.- 4-bit + LoRA is the sweet spot β LoRA 16-bit uses 4Γ more VRAM than QLoRA 4-bit.
- Minimum 300 GRPO steps before rewards move (often 1000+). Teams that train for 50 steps and demo "it's not learning" are mis-reading the signal.
- 500 rows dataset is optimal; works with 10+ β do not over-engineer curriculum at scale.
- Unsloth is GPL-licensed. If your submission needs a permissive license for judges, check the README.
Specific APIs
from unsloth import FastLanguageModel
from trl import GRPOTrainer, GRPOConfig
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3-1.7B-Instruct",
max_seq_length=4096,
load_in_4bit=True,
fast_inference=True, # vLLM shared memory
gpu_memory_utilization=0.6,
)
model = FastLanguageModel.get_peft_model(
model,
r=16,
target_modules=["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
lora_alpha=16,
use_gradient_checkpointing="unsloth", # async system RAM offload
)
trainer = GRPOTrainer(model=model, tokenizer=tokenizer, ...)
trainer.train()
model.save_lora("my_lora")
model.push_to_hub_merged("me/qwen3-grpo-wordle", tokenizer, save_method="merged_16bit")
Depth-of-help ceiling
Takes you from "free Colab T4 can't even load a 4B model" β "train a 8B with 110K ctx GRPO on one H100." Ceiling: does NOT do multi-GPU DDP/FSDP training at scale β use Torchforge for that. Also tied to supported model families (Llama/Qwen/Gemma/Phi/Mistral/gpt-oss/DeepSeek-R1-Qwen); exotic archs not supported.
Tool 4: PyTorch (+ PyTorch Foundation)
Elevator: The native ML framework underlying everything on this stack β Meta's flagship, and the reason the hackathon judging is biased toward PyTorch-native solutions.
What it does at each layer
- Tensor + autograd core (nothing new to explain here).
torch.compileβ Unsloth, vLLM, TRL all depend on this for 2β3Γ speedups.- DTensor + DeviceMesh β distributed tensors that Torchforge's TorchStore uses for resharding.
- FSDP2 β fully sharded data parallel, the path to training 70B+ with Torchforge/TorchTitan.
torch.exportβ ahead-of-time compile for deployment.
Latest features (relevant for 2026 hackathon)
- PyTorch 2.9 (Oct 2025) β required minimum for Torchforge + Monarch.
- vLLM 0.7+ integration finalized β required by TRL for colocate mode.
- Meta's Monarch (PyTorch-native distributed coordination) β open-sourced Oct 2025.
Integration points
- Everything here is built on PyTorch. Specifically, TRL requires
transformers>=5.2.0which requirestorch>=2.5.
Gotchas
- Don't pin torch below 2.5. TRL v1.2 will silently fall back and break env_factory.
- CUDA mismatch: Colab's CUDA version shifts; use
torch==X.Y.Z+cuXXXform.
Depth-of-help ceiling
Foundation layer. If you write custom CUDA ops, you're in it. Otherwise it's transparent infrastructure.
Tool 5: HuggingFace Hub / Spaces / Datasets
Elevator: The tripod of deployment β Spaces host your env server, Models host your trained checkpoint, Datasets host your curriculum.
What it does at each layer
- Spaces = Docker container runtime with auto-generated URL, public pip-install path, ZeroGPU option. Your OpenEnv env lives here.
- Models = Git LFS repos for model weights. Your trained checkpoint lives here with a Model Card.
- Datasets = Parquet/CSV/JSON on Hub. Your curriculum + eval data lives here, accessible via
datasets.load_dataset("me/my_curriculum"). - Collections = curated grouping that the OpenEnv catalog uses.
- Jobs (new 2025 Q4) =
hf jobs run --script ...cloud-executes a script on rented GPUs. - Inference Providers = serverless inference routing (for eval, not training).
Latest features (Q4 2025 β Q1 2026)
- ZeroGPU on H200 β free-tier now gets NVIDIA H200 slices (~70GB VRAM) dynamically allocated. This is the single biggest quality-of-life change in 2026.
- PRO at $9/mo includes 8Γ ZeroGPU quota = 25 min H200/day, 10Γ private storage (1TB), 2M Inference Provider credits, up to 10 ZeroGPU Spaces with Dev Mode (SSH/VS Code).
- Pay-as-you-go GPU credits: $1 per 10 min H200 beyond quota.
- Spaces Dev Mode: SSH/VS Code into running Space (PRO).
- HF Jobs β
uv run ...+ PEP 723 inline deps + cloud execution.
Integration points
- β OpenEnv:
openenv push=git pushto Space with Docker SDK. - β TRL:
GRPOTrainer(..., push_to_hub=True)writes checkpoint to Models. - β smolagents: agents can be shared via Hub.
Gotchas
- Free Spaces have CPU by default β you need to explicitly enable ZeroGPU or upgrade tier.
- Space sleep: free tier sleeps after 48h idle. Judges opening your Space will get a cold start (~30β90s). Pre-warm before demo.
- Concurrency on free Spaces is LIMITED. 1 WebSocket = 1 user. Training will starve. Duplicate to your account + upgrade.
registry.hf.space/<namespace>-<space>:latestis the Docker image format β note the dash not slash.- Dataset cards are LLM-screened. Judging is partly automated; missing YAML frontmatter = potential filter.
Specific APIs
hf login
hf upload me/my_lora ./output_dir --repo-type model
hf upload me/my_curriculum ./data.parquet --repo-type dataset
hf download openenv/echo_env --repo-type=space --local-dir=echo_env
hf jobs run --flavor a10g-small --script train.py
# Space Docker image
docker pull registry.hf.space/me-my_env:latest
from datasets import load_dataset
ds = load_dataset("me/my_curriculum", split="train")
Depth-of-help ceiling
Takes you from "I have a dataset/env/model" to "anyone in the world can pip install git+https://...." Ceiling: not a training harness, not a reward framework. And free-tier Spaces are too constrained for training β use for serving only.
Tool 6: Docker + FastAPI (OpenEnv server runtime)
Elevator: The execution sandbox in which your env server actually runs; OpenEnv generates a Dockerfile + FastAPI app that together become the thing an agent talks to.
What it does
- FastAPI β OpenEnv's
create_app(...)emits a FastAPI app with endpoints:POST /reset,POST /step,GET /state,GET /health,GET /web/(Gradio UI),WS /ws. - Uvicorn β the ASGI server hosting FastAPI.
- Docker β isolates the env: no egress (configurable), fixed CPU/RAM, reproducible build.
Latest features
- OpenEnv v0.2.3's Gradio-backed
/web/path handling (409 before reset, redirect/β/web/). - FastMCP 2.x/3.x integration in v0.2.2+.
Gotchas
--platform linux/amd64is mandatory for Mac judges.- WebSocket vs HTTP: some HF Spaces proxies drop idle WS connections after 60s. Set a heartbeat.
- Container escape risk: smolagents recommends additional sandboxing (E2B/Modal/Pyodide) for untrusted code in
coding_envuse cases.
APIs
docker build -t my_env .
docker run -d -p 8001:8000 --platform linux/amd64 my_env
curl http://localhost:8001/health
Depth-of-help ceiling
Container = containment. Beyond reliability + isolation, it doesn't help with training, rewards, or scaling.
Tool 7: Torchforge (meta-pytorch/torchforge)
Elevator: Meta's PyTorch-native, actor-based, async-first RL library (October 2025) for scalable post-training; experimental but the PyTorch-blessed path.
What it does at each layer
- Services layer (on Monarch): Distributed actor replicas with automatic load balancing + fault tolerance.
.as_service()wraps an actor class. - Service adverbs:
.route()β load-balanced single-replica call..fanout()β broadcast to all replicas..session()β sticky session for KV-cache reuse (NEW, barely documented).
- TorchStore: Distributed in-memory KV store with DTensor APIs, RDMA transfers, cross-topology resharding. Weight sync without GPU blocking.
- Monarch: Single-controller distributed coordination (vs SPMD complexity).
- Apps:
apps/sft/main(SFT),apps/grpo/main(GRPO),apps/blackjack/main(env GRPO demo).
Latest features (Q4 2025 β Q1 2026)
- Announced Oct 2025 by PyTorch team. Still "experimental, expect breaking changes."
- Together AI demo: Qwen 1.5B BlackJack GRPO on Together Instant Clusters.
- TorchStore with DTensor-based async weight syncing.
- Any-degree-of-async: same code scales from sync PPO to fully async off-policy.
Killer integration points
- β OpenEnv:
apps/grpo/mainhas an OpenEnv-integrated reference (e.g., grpo_blackjack). - β TorchTitan: underlying trainer for 70B+ scale. Forge + Titan + vLLM = Meta's internal stack.
- β Together AI / Coreweave: validated on 512Γ H100 + Instant Clusters.
Gotchas
- "Experimental" is not just a disclaimer β APIs will change. Pin git commit hash.
- Minimum 2 GPUs for GRPO. Won't run on Colab free T4.
- Monarch requires PyTorch 2.9.0+.
- ROCm path is separate (
install_rocm.sh).
Specific APIs
# Actor service
policy = PolicyActor.options(
hosts=1, procs=8, with_gpus=True, num_replicas=16
).as_service()
# Adverbs
response = await policy.generate.route(prompt) # load-balanced
await policy.update_weights.fanout(new_version) # broadcast
async with policy.session() as sess: # sticky KV
out = await sess.generate.route(prompt)
# TorchStore
import torchstore as ts
await ts.put("weights_v1", dtensor)
reshard = await ts.get("weights_v1", target_layout_dtensor)
conda create -n forge python=3.12 && conda activate forge
./scripts/install.sh
python -m apps.grpo.main --config apps/grpo/qwen3_1_7b.yaml
Depth-of-help ceiling
Massive async-scale training on many GPUs. For a 1-Colab hackathon submission it's overkill; however, mentioning it in the pitch and showing a torchforge-compatible config file is a huge "pitch differentiator" signal because judges from Meta will recognize it. Real training ceiling: limited by experimental status β stuff will break under you.
Tool 8: Google Colab
Elevator: The default GPU notebook everyone uses; $200/mo credits mentioned in the hackathon email.
2026 tier structure
- Free: T4 (16GB), time-limited sessions, CPU fallback. ~1.76 CU/hr.
- Pro ($9.99/mo): ~100 CU, L4/A100 access, longer sessions. A100 ~15 CU/hr β ~7 hrs/100 CU.
- Pro+ ($49.99/mo): background exec, priority queue, more CUs.
- Pay-as-you-go: $9.99 per 100 CU. ~57 hrs T4 or ~7 hrs A100 per $10.
- Colab Enterprise (GCP-backed): custom pricing, H100 available.
What $200 credits actually buys you
- T4 (16GB): ~114 hrs = ~4.7 days continuous. Plenty for Unsloth 1.5Bβ3B GRPO.
- L4 (24GB): ~80 hrs. The sweet spot β 2Γ T4 memory, close to A100 speed on LoRA.
- A100 (40GB): ~14 hrs. Enough for a serious 7B GRPO run or a long gpt-oss demo.
- H100 (80GB, Enterprise only): ~6 hrs for a serious reasoning eval.
Gotchas
- Compute units expire. Don't hoard.
- Disconnects: free tier disconnects after ~12 hrs regardless of activity. Pro+ has background exec.
- Disk: 100GB local, not persistent. Mount Drive or checkpoint to HF Hub every 50 steps.
- CUDA version drift: Colab sometimes upgrades CUDA mid-quarter breaking pinned wheels. Re-run
!pip installat session start. - vLLM on T4 is a pain. Unsloth's
fast_inference=Trueworks; raw vLLM often doesn't fit.
Specific commands
# Colab setup block (must-have)
!pip install -q -U "trl[openenv]==1.2.0" "transformers>=5.2.0" \
"openenv-core>=0.2.3" "unsloth" "vllm>=0.7.3" wandb
!pip install -q "openenv-textarena @ git+https://huggingface.co/spaces/openenv/wordle"
from google.colab import userdata
import os
os.environ["HF_TOKEN"] = userdata.get("HF_TOKEN")
os.environ["WANDB_API_KEY"] = userdata.get("WANDB_API_KEY")
Depth-of-help ceiling
Gets you from nothing to a running GRPO loop. Ceiling: disconnects kill long runs, single-GPU only, no SSH (unlike HF Spaces Dev Mode on PRO). For multi-GPU scale use HF Jobs or Together AI.
Tool 9: Weights & Biases (W&B)
Elevator: The experiment tracker that makes GRPO reward curves beautiful for a pitch deck.
What it does at each layer
- Run tracking: losses, rewards, KL, per-reward-function breakdowns.
- Rich media:
log_completions=Truein GRPOConfig logs completions as HTML tables per step β judges can scroll through model outputs. - Sweeps: hyperparameter search with GPU scheduling.
- Reports: shareable read-only dashboards β this is what you embed in your Devpost submission.
- Artifacts: model / dataset versioning.
Latest features (Q4 2025 β Q1 2026)
- Dedicated GRPO dashboard templates (via
wandb.integration.trl). - Weave β W&B's LLM observability layer, can trace env interactions end-to-end per episode.
- Reports v3 β interactive reports with live-updating charts, publishable to a URL.
Integration points
- β TRL:
GRPOConfig(report_to="wandb", log_completions=True)β one line. - β HF Hub: W&B run URL can be added to Model Card.
- β Devpost demo: embed live W&B report URL in your submission β judges see real-time training.
Gotchas
rewardmetric is unweighted sum (TRL issue #5352, Mar 2026) even ifreward_weightsare non-uniform. Model trains correctly but chart is misleading. Log your own weighted metric manually.- Free tier: 100GB artifact storage β plenty for a hackathon.
- Entity scoping: if you log under a personal entity vs team, URL structure differs; agree with teammates upfront.
Specific APIs
import wandb
wandb.init(project="openenv-hackathon",
name="qwen3-wordle-grpo",
config={"model": "Qwen/Qwen3-1.7B", "env": "wordle"})
# In GRPOConfig:
report_to="wandb"
log_completions=True
run_name="qwen3-wordle-grpo"
# Log custom reward components
wandb.log({"reward_weighted": w_r * r for r in ...})
Depth-of-help ceiling
Tracking and presentation. Doesn't touch training logic. Ceiling: if you need evaluation-sets-vs-model matrix comparisons, W&B Tables are good but eventually you'll roll your own Streamlit dashboard.
Tool 10: smolagents
Elevator: HuggingFace's minimalist "code-writing agent" library (~1000 LOC) β agents that emit Python actions rather than JSON tool calls.
What it does at each layer
- Agent loop:
CodeAgentgenerates Python code β executes in sandbox β captures output β loops. - Sandbox layer: Executes code via Blaxel, E2B, Modal, Docker, or Pyodide+Deno WebAssembly.
- Tool layer: Tools are Python functions auto-introspected; shared via Hub.
- Model-agnostic: transformers, ollama, OpenAI, Anthropic, LiteLLM.
Latest features (Q4 2025 β Q1 2026)
- Pyodide+Deno WASM sandbox β no Docker needed, runs in-browser/WASM.
- Full Hub integration for sharing agents.
- Production-grade first-class OpenAI/Anthropic support via LiteLLM.
Integration points
- β OpenEnv's
coding_env: smolagents is the sandbox providing persistent Python context, stdout/stderr/exit capture, detailed error handling. - β TRL: smolagents agent can be the thing you train; wrap it in an env class with
.run()as a tool method. - β HF Hub:
agent.push_to_hub("me/my-agent").
Gotchas
- Sandbox choice matters for screener: Pyodide = lightest, E2B = best isolation, Docker = mid. Pick one and pin.
- Code agents can hang if they write infinite loops. Set
max_stepsand kill switches.
Specific APIs
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool
agent = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct"),
executor_type="e2b", # or "docker", "pyodide"
max_steps=10,
)
result = agent.run("Find top 3 earthquakes in the past week.")
Depth-of-help ceiling
Great for the "agent that writes Python" use case, especially in coding_env-style problems. Ceiling: not optimized for multi-agent orchestration (use LangGraph or OpenClaw for that) and its sandbox is not production-hardened.
Tool 11: MCP (Model Context Protocol) in OpenEnv
Elevator: Anthropic's open standard for LLMβexternal-tool interop, now native to OpenEnv via RFC 003 and RFC 004 (MCPEnvironment).
What it does at each layer (in OpenEnv context)
- Discovery:
ListToolsActionmaps to MCPtools/listJSON-RPC. - Invocation:
CallToolAction(tool_name, parameters)maps to MCPtools/call. - Primitives: Resources (GET-like data), Tools (POST-like ops), Prompts (reusable templates).
- Transport: FastMCP 2.x/3.x (HTTP + SSE or WebSocket).
- Modes in OpenEnv v0.2.2: production mode (real MCP server) + simulation mode (replayed traces for reproducible eval) + code mode (CodeAct execution).
Latest features
- RFC 003 (Feb 2026): MCPEnvironment class, ListTools/CallTool actions, JSON-RPC marshaling, local server bypass for perf, composite parentβchild delegation.
- RFC 004 (In Review, 2026-04): "Actions as tool calls" β make your env's native actions be MCP tool calls. Zero translation overhead. Better introspection for training.
Killer integration points
- β Any MCP server: Your env can pull in Slack, GitHub, Filesystem, Puppeteer, etc. MCP servers.
- β TRL:
environment_factory+ MCP-backed env = model learns to call any MCP tool. - β Claude Code / OpenClaw (RFC 005): your env's actions callable by any MCP client.
- β smolagents: smolagents can invoke MCP tools directly.
Gotchas
- FastMCP version pinning: 2.x vs 3.x semantics differ on tool schema. Pin explicitly.
- JSON-RPC marshaling overhead unless you use local-server bypass.
- Reserved-name validation: certain tool names (e.g.,
reset,step) collide with OpenEnv internals β v0.2.2 validates this at server start.
Specific APIs
from openenv.mcp import MCPEnvironment, ListToolsAction, CallToolAction
env = MCPEnvironment(
mcp_server_urls=["http://localhost:3333", "http://localhost:3334"],
mode="production", # or "simulation" or "code"
)
env.reset()
tools = env.step(ListToolsAction()).observation.metadata["tools"]
result = env.step(CallToolAction(
tool_name="github.search_repos",
parameters={"query": "pytorch grpo"},
)).observation.metadata["result"]
Depth-of-help ceiling
Massive β MCP is the emerging standard. Ceiling: MCP ecosystem is new so many servers are buggy. For the hackathon, prefer first-party MCP servers (Anthropic's filesystem/github/puppeteer).
Integration recipe β end-to-end submission
Here is the recipe that plugs everything together; the "one Colab cell to rule them all":
# === 1. Install (Colab, first cell) ===
!pip install -q -U "trl==1.2.0" "transformers>=5.2.0" "openenv-core>=0.2.3" \
"unsloth" "vllm>=0.7.3" wandb datasets
!pip install -q "openenv-<yourenv> @ git+https://huggingface.co/spaces/<you>/<yourenv>"
# === 2. Auth ===
import os
from google.colab import userdata
os.environ["HF_TOKEN"] = userdata.get("HF_TOKEN")
os.environ["WANDB_API_KEY"] = userdata.get("WANDB_API_KEY")
# === 3. Unsloth-patched model (MUST be first) ===
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Qwen3-1.7B-Instruct",
max_seq_length=4096,
load_in_4bit=True,
fast_inference=True,
)
model = FastLanguageModel.get_peft_model(model, r=16, lora_alpha=16,
target_modules=["q_proj","k_proj","v_proj","o_proj","gate_proj","up_proj","down_proj"],
use_gradient_checkpointing="unsloth")
# === 4. Env (your innovation here) ===
from your_env import YourEnvClient, YourAction
class YourToolEnv:
def __init__(self):
self.client = YourEnvClient(base_url="https://<you>-<yourenv>.hf.space")
self.reward = 0.0
def reset(self, **kwargs) -> str:
self.reward = 0.0
return self.client.reset().observation.initial_prompt
def act(self, move: str) -> str:
"""Make a move.
Args:
move: the move to perform
Returns: result description
"""
res = self.client.step(YourAction(move=move))
self.reward = res.reward
return res.observation.description
# === 5. Reward + curriculum dataset ===
from datasets import load_dataset
ds = load_dataset("me/curriculum", split="train") # Tool 5: Datasets
def reward_func(environments, **kwargs):
return [env.reward for env in environments]
# === 6. Train ===
from trl import GRPOTrainer, GRPOConfig
trainer = GRPOTrainer(
model=model, tokenizer=tokenizer,
train_dataset=ds,
reward_funcs=[reward_func],
args=GRPOConfig(
use_vllm=True, vllm_mode="colocate",
num_generations=4, gradient_accumulation_steps=16,
max_completion_length=4096,
report_to="wandb", log_completions=True,
push_to_hub=True, hub_model_id="me/qwen3-your-env",
loss_type="gspo",
),
environment_factory=YourToolEnv,
)
trainer.train()
model.push_to_hub_merged("me/qwen3-your-env-merged", tokenizer)
Dependency order of operations:
- Write env β
openenv pushβ Space live. - Duplicate the Space to your account (for concurrency).
- Colab: install, auth.
- Unsloth load model.
- Wrap env in TRL-compatible class.
- Train w/ W&B logging.
- Push model to Hub.
- Make a W&B Report URL.
- Link everything in Devpost.
Pitch differentiator features (things 95% of other teams won't use)
Multi-environment GRPO training (TRL v1.2
environment_factory+ per-env reward masking withNonereturns). Train one model on Wordle + Sudoku + Your-Env simultaneously and show differential skill curves. Nobody's shipping this yet β it was documented publicly the same week as the hackathon email.MCPEnvironment with mode=simulation (OpenEnv v0.2.2). Use simulation mode to replay deterministic MCP traces during eval β gives judges reproducible metrics. Pair with production mode for training.
Rubrics (RFC 004) as reward source. Ship a rubric config that uses an LLM-as-judge for reward with delayed signals instead of hand-written reward funcs. Almost no team will do this.
Torchforge config file, even if you don't train on it. Commit a
forge.yamland show a diagram of how your env scales to Monarch actors. Meta judges will notice.AsyncGRPOTrainer + chunked LM head (TRL v1.1). 44Γ peak memory reduction. Lets you train 7B on an A100 where other teams are stuck at 3B.
Unsloth long-context (Jan 2026). Qwen3-8B GRPO at 110K context on one H100 β if your env benefits from long horizons (e.g., multi-step reasoning), this is the moat.
RFC 005 agentic harness integration. Make your env a skill that Claude Code or OpenClaw can invoke. The "meta" angle: your env improves coding agents.
SSDTrainer (TRL v1.2) for self-improvement. No reward model needed β model distills its own high-quality samples. Pairs beautifully with a "self-improving multi-agent env" narrative.
HF Jobs for cloud training.
uv run examples/scripts/openenv/<yours>.pywith PEP 723 inline deps β one command cloud-trains on HF's GPUs. Demo-friendly.GenericEnvClient for universal eval. Use
GenericEnvClient/GenericActionto eval your trained model against ANY OpenEnv env on the Hub without installing their code β flex "universal generalization."
Gotchas that break the LLM screener (consolidated)
The hackathon has an automated LLM screener gate before human judging. These are the things that will kill you there:
- Docker
--platform linux/amd64missing β Space doesn't build on judge's Mac. max_concurrent_envs=1(default) β training hangs, reward is 0, screener sees dead run.- Tool method missing
Args:docstring β TRL builds broken tool schema, model never calls the tool, reward stays 0. environment_factory=MyEnv()(passed as instance not class) β single-rollout stuck, reward flat.max_completion_length=512on multi-turn env β episodes cut mid-game.num_generationsdoesn't divide batch_size Γ grad_accum β GRPO crash.- Using a shared community Space β concurrency throttle, silent stall.
transformers<5.2.0βenvironment_factorysilently ignored.- Missing Model Card / Dataset Card YAML frontmatter β LLM screener may flag as "incomplete."
- Unsloth imported AFTER transformers β monkey-patch fails, slow training, OOM.
- Free Space sleep β judge clicks your demo link, cold start, first call 404s.
- GRPO run <300 steps β rewards don't move, looks like "model not learning."
- Chat template missing
{% generation %}markers β assistant-only loss broken (v1.1 auto-patches, but only for SFT β GRPO does not). - Port 8000 collision between vLLM and env β map env to 8001.
- No duplicate of env Space for training β training will compete with public demo traffic.
Recommended integration pattern for a Multi-Agent + Self-Improvement env
Since the prior research pointed at multi-agent + self-improvement as a winning category, here's the canonical stack:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Devpost submission page β
β ββ Links to: Space, Model, Dataset, W&B Report, Colab β
β ββ Embedded video demo β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β²
ββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββ
β Hugging Face Hub (Tool 5) β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββ β
β β Space β β Model β β Dataset β β
β β (env server)β β (GRPO ckpt) β β (curriculum) β β
β β FastAPI+ β β LoRA merged β β multi-agent β β
β β Docker β β via Unsloth β β scenarios β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββ β
βββββββββ²ββββββββββββββββββ²ββββββββββββββββββ²βββββββββββββββ
β WebSocket β push_to_hub β load_dataset
β (OpenEnv) β (Unsloth) β (Datasets)
β β β
βββββββββΌββββββββββββββββββΌββββββββββββββββββΌβββββββββββββββ
β β Colab / HF Jobs / Together AI (Tool 8) β
β βββββ΄ββββ ββββββββββ΄βββββββββ βββββββββ΄βββββ β
β βOpenEnvβββββΆβ TRL v1.2 βββββ Dataset β β
β β env β β GRPOTrainer β β curriculum β β
β β clientβ β env_factory= β ββββββββββββββ β
β βββββ¬ββββ β MultiEnvClass β β
β β β β β
β β β Unsloth patch βββββΆ W&B (Tool 9) β
β β β + GSPO loss β log_completions β
β β β + SSDTrainer β Report URL β
β β β (self-improve) β β
β β ββββββββββ¬βββββββββ β
β β β β
β β βΌ β
β β Merged Qwen3-1.7B/8B LoRA β
β β β
β βββΆ MCPEnvironment (RFC 003/004) β
β ββ mode="production" for training β
β ββ mode="simulation" for reproducible eval β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Multi-agent angle: Build a MultiAgentEnv where multiple agent instances (could be the SAME model at different temperatures, or specialist LoRA adapters) interact. Each agent gets its own set of tool methods. Reward is emergent from their interaction β e.g., a debate scoring game, a coordination puzzle, a trade simulation.
Self-improvement angle: Use SSDTrainer (v1.2) so model distills from its own high-reward trajectories. After N steps, use the just-trained model as the new teacher. Combined with Unsloth's long-context RL, you can demo: "our model learns from itself without a reward model" β a huge narrative win.
Key implementation files to write:
envs/my_env/src/envs/my_env/server/app.pyβ FastAPI app withcreate_app(..., max_concurrent_envs=64).envs/my_env/src/envs/my_env/environment.pyβ theEnvironmentsubclass.envs/my_env/src/envs/my_env/models.pyβ PydanticAction/Observation.train.pyβ the Colab cell above, withMultiEnvClass+ SSDTrainer.README.mdβ with--platform linux/amd64docker command front and center.rubric.yamlβ LLM-as-judge reward config (RFC 004).wandb_report_url.mdβ pin to top of README.
Quick reference: "what version of everything do I pin?"
torch >= 2.9.0
transformers >= 5.2.0 # required for environment_factory
trl == 1.2.0 # pin exactly; experimental API
openenv-core >= 0.2.3
unsloth (latest)
vllm >= 0.7.3
datasets (latest)
wandb (latest)
fastmcp >= 3.0 # for MCPEnvironment
smolagents (latest) # if using coding_env
Sources
- OpenEnv Releases (GitHub)
- OpenEnv RFC 003: MCP Support
- OpenEnv RFC 004: Actions as Tool Calls
- OpenEnv README
- TRL Releases (GitHub)
- TRL OpenEnv Integration Docs
- TRL GRPO Trainer Docs
- Unsloth RL Guide
- Unsloth GRPO Long Context
- Unsloth gpt-oss RL
- Introducing Torchforge (PyTorch Blog)
- Torchforge GitHub
- HuggingFace Pricing
- HuggingFace ZeroGPU Docs
- Google Colab Pricing
- smolagents GitHub
- Building the Open Agent Ecosystem (HF Blog)
- TRL GRPO+WandB Issue #5352