Skip to main content

Data & usage flow

This is the lifecycle a researcher or training loop actually drives, start to finish. Five stages: define → build → provision → use → evaluate, with cleanup running continuously in the background.

1 · Define the environment​

You describe what the environment needs — a base image, a user, your project, optionally an IDE — by composing plugins with the fluent Image API. No Dockerfile by hand.

from idegym.image.builder import Image
from idegym.plugins.defaults.image import User, Project, Permissions

image = (
Image.from_base("ghcr.io/jetbrains-research/idegym/server-debian-bookworm-20250520-slim:latest")
.with_plugin(User(username="devuser", uid=2000, gid=2000, sudo=True))
.with_plugin(
Project.from_git(
url="https://github.com/owner/my-repo.git",
ref="abc123",
owner="devuser",
target="/home/devuser/project",
)
)
.with_runtime(runtime_class_name="gvisor", resources={...})
)

Each plugin updates a shared BuildContext and emits a Dockerfile fragment. Calling image.to_spec() compiles the whole thing into an ImageBuildSpec (the final Dockerfile + metadata).

2 · Build the image​

The image definition is serialized to YAML and submitted to the orchestrator, which runs the build through a pluggable backend — Kaniko in-cluster by default (no Docker daemon on the nodes), or GKE Cloud Build — and pushes the result to a registry.

summary = await client.jobs.build_and_push_images(path=yaml_path, namespace="idegym", timeout=600)
image_tag = summary.jobs_results[0].tag

A shared ImageBuildService forwards download credentials (for private project repos) to the backend and polls the build to completion. Plugins that COPY bundled files (e.g. the IDE plugins) ship those assets themselves, so a build needs no checkout of the idegym repo. → Image builder

3 · Provision a sandboxed environment​

Starting a server creates a Kubernetes Deployment from the built image. The pod pulls the image and boots Supervisor → FastAPI server (and any in-pod IDE process). With the gvisor runtime class, the container runs in a syscall-filtering sandbox.

async with client.with_server(image_tag=image_tag, server_name="my-server", runtime_class_name="gvisor") as server:
...

If a matching finished server already exists, IdeGYM can reuse it (optionally restarting or resetting project state) instead of cold-starting — and can restore from a pod snapshot to skip warm-up like project indexing. → Orchestrator

4 · Use the environment​

You never connect to the pod directly. Requests go to the orchestrator, which forwards them (HTTP or MCP, including WebSockets for OpenEnv) into the server pod. Inside, the tools plugin executes them.

result = await server.execute_bash("python -m pytest -q")
await server.create_file("/home/devuser/project/new.py", "print('hi')\n")
await server.patch_file("/home/devuser/project/main.py", patch="--- ...")

Every forwarded request and response is persisted in PostgreSQL, so you can replay or compute rewards offline later. → What runs in the pod · Tools

5 · Evaluate with rewards​

To turn an agent's actions into a training signal, ask the environment to score itself:

result = await server.test_reward(test_script="cd /project && python -m pytest -q")
score = result.passed / (result.passed + result.failed)

Three built-in reward kinds — compilation, setup, and test — run a script in the sandbox and return a structured result. → Rewards & tools

The RL / eval inner loop​

♻ Cleanup (always on)​

A background watcher loop reconciles the database against the live cluster every interval: it evicts servers whose clients are gone, detects crashed pods (over their restart budget), and frees quota — no manual teardown. Stopping a client tears down all its alive servers. → Watcher

See it as one diagram​

Ready for the whole topology, with every node clickable?

→ Open the interactive architecture