Date: 14 August 2026

That is Sim2Policy, my entry for the Nebius Serverless Challenge 2026.
Nebius ran the first Serverless AI Builder's Challenge this year, and Sim2Policy was selected as an Awesome Serverless award winner โ a Nebius Serverless AI Champion badge and a $1,000 AI Cloud grant.
Everything below is the project that won it. It is still live, still free, and it will train your robot too.
Training a robot policy in the cloud is easy. Keeping the proof after the machine vanishes is hard. Serverless GPU jobs spin up, train, and disappear โ and usually take the evidence with them.
Sim2Policy fixes that. Each run trains a policy on a bounded Serverless AI Job and leaves behind a durable, reproducible result. You never touch a GPU, an image, or a config file โ you just pick an example and watch it learn.
Every run leaves behind:
Under the hood there are two training engines behind the same simple button: a dependable CPU path for the classic control robots, and a GPU-parallel path for the big quadruped and humanoid. You never have to know which one ran โ the platform picks it for you.
The landing page is a gallery of runs that already happened. Anyone can browse it โ no account, no sign-up โ and every card carries the backend that ran it and the success criterion it was judged against.

Here is what those seven runs actually cost me, straight off the jobs:
| Run | Backend | Steps | Duration | Cost | Result |
|---|---|---|---|---|---|
| Go1 Walker | MJX ยท H100 | 200,000,000 | 16m 48s | $0.83 | โ velocity 0.97 โฅ 0.5 |
| G1 Rough Terrain | MJX ยท H100 | 250,511,360 | 1h 45m | $2.73 | โ velocity 0.74 โฅ 0.4 |
| Walker2D Stride | SB3 ยท CPU | 5,000,000 | 29m 32s | $0.10 | โ reward 5,314 โฅ 1,800 |
| Hopper Balance | SB3 ยท CPU | 5,000,000 | 21m 00s | $0.07 | โ reward 3,632 โฅ 1,000 |
| Ant Explorer | SB3 ยท CPU | 3,000,000 | 21m 34s | $0.07 | โ reward 2,975 โฅ 1,000 |
| HalfCheetah Sprint | SB3 ยท CPU | 3,000,000 | 12m 41s | $0.04 | โ reward 3,332 โฅ 1,500 |
| Reacher Target | SB3 ยท CPU | 1,000,000 | 2m 53s | $0.01 | โ reward โ5.6 โฅ โ10 |
$3.84 for the whole gallery โ the sum of the unrounded per-run costs, so it lands a cent under the column above. The flagship Go1 quadruped trained 200 million simulation steps on a single Nebius H100 in under seventeen minutes for 83 cents. This is real GPU reinforcement learning at coffee-money prices.
Click any card and you get the whole evidence trail: the criterion, the primary metric, the observed duration and cost, a rollout video, the full evaluation, and a one-click policy bundle โ all pinned to the exact acceptance revision that published it.

The G1 humanoid sat in that gallery for weeks as a recording, with success: false printed on
the page. It crossed rough ground at 0.86 m/s โ comfortably past the 0.4 velocity bar โ and then
fell, in all twenty evaluation episodes. The criterion says velocity and not fallen. Zero
clean finishes.
The obvious reading of "0/20 upright" is an undertrained policy, and the obvious fix is more steps. 348 million steps and $3.24 had already bought exactly nothing on that metric. Here is why.
First, the robot ran out of world. The rough-terrain scene I had inherited is a finite 20 m ร
20 m height field, and the episode spawns dead centre. An episode is 1,000 steps at 20 ms, so
20 seconds. At the commanded 0.8โ1.0 m/s the robot must cover 16โ20 m; the farthest point on
that patch is 14.14 m away, diagonally. No policy could have finished an episode โ every run
walked off the edge of the terrain and fell into nothing. Worse, training was making it worse:
over the same checkpoints, velocity climbed from 0.75 to 0.96 m/s, which just got the robot to
the edge sooner. The fix was a server-owned 60 m ร 60 m scene, plus an invariant that now refuses
to launch any config where velocity ร horizon ร timestep exceeds the worst-case distance to the
edge.
Second, nothing paid it to stay upright. The pinned G1 reward scores velocity tracking and
charges โ100 once, on termination, with discounting at 0.97 per 20 ms step โ a 0.67-second
lookahead. A fall five seconds out discounts to 5e-4; the critic cannot see it coming, and the
penalty arrives as noise. The other humanoid in the very same package is configured the opposite
way: a small per-step alive bonus and no termination penalty. Adopting that pair took the flat
transition gate from 8/10 episodes to 10/10, and rough acceptance from nothing to 20/20.

0.74 m/s, twenty full-horizon episodes, zero falls, $2.73. Both fixes changed the problem, not the budget โ and I only found them because the failing run stayed published, with its real numbers, long enough to be argued with. A platform that only shows you its wins is a brochure, not an experiment log.
The gallery is the demo. The product is the next part: give an email, get a personal space, and train your robot. Here is the whole flow, run end to end on the live site.
Upload one self-contained MJCF file, up to 1 MiB. The validator rejects DTDs and entities before it even parses, then archives, includes, plugins, meshes, textures, height fields, external paths, and any non-primitive geometry. What comes back is a SHA-256 digest and a structural summary โ bodies, joints, actuators, geoms โ so you know exactly what the server accepted.

Two primitive-only sample robots are downloadable right there, and they run through the same validator as your upload, so there is no privileged path.
A robot model is not a training environment. It describes bodies and joints; it says nothing about observations, rewards, termination, or evaluation. So the setup builder keeps those server-owned: you pick a locomotion task, a scene preset, and up to six bounded catalog objects.

No reward code, no scene XML, no remote URLs, no uploaded meshes. You get choices, not footguns โ and because every choice comes from a published catalog, validation stays deterministic.
Before the Start Training button unlocks, a bounded CPU job actually compiles your robot in the server-owned scene, runs deterministic rollout and render gates, checks the Gymnasium/SB3 contract, and smoke-tests a PPO save/reload. It took about four minutes for mine.

Preparation means technically compatible, not guaranteed to converge. That distinction is the whole reason the gate exists: it fails fast and cheap on a broken model instead of burning a full training budget to discover the same thing.
Then you press Start training โ and that is the only way a custom job is ever created. The API endpoint takes the setup identity and an idempotency key, and nothing else. Backend, algorithm, hardware, image, command, and PPO settings are all rejected with a 422 if you try to send them.

Under twenty minutes later โ queue, train, render, evaluate โ the same evidence page the gallery runs get, for a robot the server had never seen before:

| Robot | uploaded quadruped, 9 bodies ยท 9 joints ยท 8 actuators |
|---|---|
| Profile | custom-ppo-quick-v3 โ 3,000,000 steps, 16 parallel envs |
| Compute | Nebius cpu-d3 ยท 16vcpu-64gb |
| Training runtime | 15m 39s |
| Cost | $0.10 |
| Evaluation | 20 episodes ยท mean reward 4,819 ยฑ 17 ยท fall rate 0% |
| Verdict | Task threshold met โ success rate 100% |
It walks. Twenty of twenty evaluation episodes run the full 1,000-step horizon, none of them falls, and the gait averages 0.83 m/s for 16.7 m of forward progress per episode. The spread is tiny โ 0.821 to 0.843 m/s across all twenty โ which is the part that actually says "gait" rather than "lucky episode".

That 100% is the number I had to earn, and not with training budget. "Walk forward" is scored by a server-owned reward contract, and three separate times that contract certified something that was not walking:
Every one of those passed every check that existed when it ran. The fix was a third measurement: the horizontal distance from each foot to the joint carrying its leg, as a fraction of that leg's reach. Feet under the hips reads 0.00โ0.27. A trot reads 0.29. The splits reads 0.82. Nothing else in the contract could tell them apart โ and the run above sits at 0.25.
One honest note that no amount of tuning fixes: it walks in a deep crouch, 0.32 m of body height on 0.59 m of leg. Every joint on this hand-made quadruped is a pitch hinge, so the only way it can correct a sideways lean is to extend one side's legs further than the other's โ which works worst when the legs are straight. I tested raising the height target; the robot ignored the taller ask, leaned instead, and walk-forward dropped to 15/20. The crouch is the morphology, not the reward.
Ten cents and sixteen minutes of compute for a policy, a video, and twenty episodes of evidence โ which is precisely what a cheap, bounded, disposable job is for. The policy bundle is right there: checkpoint, resolved configuration, evaluation, versions and checksums, 1.7 MiB, one click. And the checkpoint inside it is the best one the run produced, not whichever one happened to be last.
A tiny always-on VM in the Nebius cloud runs the app and launches disposable training jobs. The user stays in the browser. The cloud does the rest.

The control plane is one saas-server VM running single-node k3s with ArgoCD. GitHub
Actions builds the app image, pushes it to the Nebius registry with an immutable tag, and commits
that tag to the deploy manifests; ArgoCD reconciles it. Secrets come from MysteryBox into
Kubernetes Secrets through root-owned reconcilers, so nothing sensitive lives in Git. All of it โ
registry, bucket, least-privilege identity, VM, security group โ is OpenTofu.
The data plane is entirely ephemeral. There is no training cluster to keep warm.
cpu-d3 shapes for classic control
and custom robots. Each job gets the right one automatically.How a run works: the job runs PPO for a fixed number of steps, checkpoints to S3 as it goes,
then renders rollout videos and runs a deterministic evaluation before publishing the result. A
checkpoint is uploaded completely before latest.json advances, so an interrupted job resumes
instead of starting over.
What you can configure: for the gallery, the example and an optional seed. For your own robot, the locomotion task, a scene preset, and a few bounded objects. Everything else stays server-side.
The training plane has no idle cost. Seven gallery runs, a preparation gate, and a custom training job โ every one of them a job that started, did its work, wrote its artifacts to S3, and vanished. The only thing running around the clock is one small VM serving a web app.
That is the shape I would want for any research workload: durable artifacts, disposable compute, and a bill that matches the work actually done.
With one hosted button and a bounded serverless job, I can turn an uploaded MJCF file into a trained locomotion policy, a rollout video, and a downloadable bundle โ without the user ever touching a GPU, an image, or a config file. Nebius Serverless AI Jobs supply the compute, k3s and Argo CD keep the control plane reconciled, OpenTofu provisions the whole account, and S3 makes every run outlive the machine that produced it.
The code is available in my GitHub repository, including the OpenTofu stack, the GitOps manifests, and the behavioural specs.
Feel free to connect with me on LinkedIn.
I hope you enjoyed this article.
#NebiusServerlessChallenge