Synthetic Sandbox for Training Machine Learning Engineering Agents
Organizations: Meta AI
Abstract
As large language model agents advance beyond software engineering (SWE) tasks toward machine learning engineering (MLE), verifying agent behavior becomes orders of magnitude more expensive: while SWE tasks can be verified via fast-executing unit tests, MLE verification requires running full ML pipelines -- data preprocessing, model training, and metric evaluation -- on large datasets at each rollout step, rendering trajectory-wise on-policy reinforcement learning (RL) prohibitively slow. Existing approaches retreat to supervised fine-tuning (SFT) or offline proxy rewards, sacrificing the exploration and generalization benefits of on-policy RL. We observe that sandbox data size is the primary source of this bottleneck. Based on this insight, we introduce SandMLE, a multi-agent framework that generates diverse, verifiable synthetic MLE environments from a small number of seed tasks, preserving the structural and technical complexity of real-world problems while constraining datasets to micro-scale (each task is paired with only 50-200 training samples). Through extensive experiments, we show that SandMLE reduces execution time by over 13 times, enabling large-scale, on-policy trajectory-wise RL for the first time in the MLE domain. On MLE-bench-lite, SandMLE yields significant gains over SFT baselines across Qwen3-8B, 14B, and 30B-A3B, with relative medal rate improvements ranging from 20.3% to 66.9%. Furthermore, the trained policy generalizes across unseen agentic scaffolds, achieving up to 32.4% better HumanRank score on MLE-Dojo.
Figures & tables
| Model | Valid Sub. | Above Median | Bronze | Silver | Gold | Any Medal |
|---|---|---|---|---|---|---|
| Deepseek-V3.1 | 90.9 | 36.4 | 0.0 | 4.5 | 18.2 | 22.7 |
| Gemini-2.5-flash | 81.8 | 45.5 | 4.5 | 4.5 | 13.6 | 22.7 |
| Claude-4.5-Sonnet | 95.5 | 31.8 | 0.0 | 4.5 | 27.3 | 31.8 |
| Qwen3-8B | ||||||
| Qwen3-8B-Base | 68.2 | 18.2 | 0.0 | 4.5 | 9.1 | 13.6 |
| Qwen3-8B-Seed-SFT | 72.7 | 18.2 | 4.5 | 0.0 | 9.1 | 13.6 |
| Model | Framework | Valid Sub. | Above Med. | Bronze | Silver | Gold | Any Medal |
|---|---|---|---|---|---|---|---|
| Qwen3-14B | |||||||
| Qwen3-14B-Base | AIDE | 100.0 | 36.4 | 0.0 | 4.5 | 22.7 | 27.3 |
| Qwen3-14B-Seed-SFT | AIDE | 100.0 | 31.8 | 0.0 | 9.1 | 9.1 | 18.2 |
| Qwen3-14B- SandMLE | AIDE | 100.0 | 40.9 | 0.0 | 13.6 | 18.2 | 31.8 |
| Qwen3-14B-Base | AIRA | 100.0 | 22.7 | 0.0 | 0.0 | 9.1 | 9.1 |
| Qwen3-14B-Seed-SFT | AIRA | 95.5 | 22.7 | 0.0 | 0.0 | 13.6 | 13.6 |
| Model | Framework | Valid Sub. (%) | HumanRank Score |
|---|---|---|---|
| Claude-4.5-Sonnet | MLE-Agent | 91.9 | 54.09 |
| Qwen3-14B | |||
| Qwen3-14B-Base | MLE-Agent | 27.4 | 9.62 |
| Qwen3-14B-Seed-SFT | MLE-Agent | 3.2 | 0.65 |
| Qwen3-14B- SandMLE | MLE-Agent | 40.3 | 12.55 |
| Qwen3-14B-Base | AIDE | 74.2 | 37.73 |
| Model | Reward Type | Valid Sub. | Above Median | Bronze | Silver | Gold | Any Medal |
|---|---|---|---|---|---|---|---|
| Qwen3-8B | Sparse Reward | 59.1 | 22.7 | 0.0 | 4.5 | 9.1 | 13.6 |
| Dense Reward ( SandMLE ) | 63.6 | 27.3 | 0.0 | 4.5 | 18.2 | 22.7 | |
| Qwen3-14B | Sparse Reward | 77.3 | 31.8 | 4.5 | 0.0 | 13.6 | 18.2 |
| Dense Reward ( SandMLE ) | 77.3 | 27.3 | 4.5 | 4.5 | 13.6 | 22.7 | |
| Qwen3-30B | Sparse Reward | 86.4 | 18.2 | 4.5 | 4.5 | 4.5 | 13.6 |
| Dense Reward ( SandMLE ) | 100.0 | 36.4 | 0.0 | 13.6 | 13.6 | 27.3 |
Appendix figures & tables6 assets
Supplementary material from the paper’s appendix.
Appendix
| ReAct Framework Prompts |
|---|
| System Prompt You are an expert Kaggle competitor. Produce one Python script that trains a model and writes submission.csv for the dataset in the user prompt. Rules: - Use only already-installed common libraries (no installs). - Use the PythonInterpreter tool to iteratively write/run/update your script. - After producing a submission, use the Score tool to grade it; if the score is unsatisfying, keep refining the code and re-grading until you are satisfied. - Be concise and task-focused. Loop: 1) You are a multi-turn generation agent: in each turn, propose/refine the script or reasoning, then wait for environment/tool feedback. 2) Execute via the tool until it runs cleanly and produces the file. STRICT: each response may contain exactly ONE tool_call block—do not emit multiple tool calls. 3) After generating the code, the Python environment will provide feedback. You must observe at least one tool feedback (execution result wrapped in tool_response ... /tool_response tags) before deciding to end. Only when feedback looks good do you reply with answer submission /answer ; otherwise continue iterating (do not output answer tags). 4) Use PythonInterpreter to run updated code; use Score tool to grade submission.csv . Repeat this refine-grade loop until the submission is acceptable, then end with answer submission /answer . Tool usage: For each function call, return a json object with function name and arguments within tool_call ... /tool_call XML tags: - Wrap executable code exactly like this: tool_call python code # Your Python code here print("Hello World") /code /tool_call Code inside those tags runs in Python; keep the tool name python and include code ... /code . - To grade the submission.csv file, you need to use Score tool and output json object like this: tool_call {"name": "Score", "arguments": {"competition_id": "competition id here, such as aerial-cactus-identification, which can be found in the task description"}} /tool_call Current date: |
| User Prompt You are solving the task below. Follow the requirements precisely. {mle task description} Your code should adhere to the following requirements: - Prefer and explicitly use GPU (CUDA) acceleration when available (one A100 GPU should be available): move models/tensors to GPU and handle CPU fallback if CUDA is not present. - Each Python interpreter execution must finish within a given time limit. - Overall runtime limits: the agent may take up to max LLM calls turns. - Load train/test data from the provided dataset folder ( ## Dataset Folder ). Please first check the data files and their formats (file types, column names, row counts, etc.). - Match the exact columns/headers in sample_submission.csv ( ## Dataset Folder ) and write submission.csv to the current directory . - Use only common preinstalled libraries (no installs). - DO NOT display progress bars due to the context window limit. If you have to use function integrated with progress bars, disable progress bars or use the appropriate parameter to silence them. - Please restrict the use of external libraries to the common libraries. - The task is an out-of-date competition, so please ignore the timeline in the task description. |
| Data Strategist Prompt Template |
|---|
| You are an expert Meta-Learning Analyst. Your goal is to extract the “Structural DNA” of a machine learning dataset in this folder. You must IGNORE the domain context (the “Story”). For example: - If the data is about “Titanic Survivors”, do NOT mention ships, passengers, or icebergs. - If the data is about “House Prices”, do NOT mention kitchens, square footage, or neighborhoods. Instead, convert these into Abstract Mathematical Concepts . - “Age” “Continuous variable, positive, right-skewed”. - “Cabin Number” “High-cardinality categorical, high missing rate”. - “Survived” “Binary Target, Class Imbalance 60/40”. CRITICAL INSTRUCTION: 1. Detect the Modality: Determine if the problem is Tabular, Computer Vision (Images), NLP (Text), Audio or Graph. 2. IGNORE Domain: Do not mention “X-Rays”, “Customer Reviews”, or “Bird Calls”. Describe the signal mathematically. 3. Select the Schema: structure your JSON output according to the detected modality. OUTPUT SCHEMA (Polymorphic): Return ONLY a raw JSON object with this structure: { "modality": "Tabular | Image | Text | Audio | Graph", "task_type": "Classification | Regression | Segmentation | Object Detection", "dataset_stats": { "sample_count": Integer, "is_imbalanced": Boolean }, // --- UNIVERSAL TARGET INFO --- "target_info": { "type": "Label | BoundingBox | Mask | Text", "cardinality": Integer, "distribution": "Balanced | Long-tail" } } |
| You are a Synthetic Data Strategist. I will provide the “Structural DNA” of a dataset. Your goal is to brainstorm 5 distinct “Industry Scenarios” that could naturally generate data with this exact structure. INPUT DNA: {dna_json} CONSTRAINT: The scenarios must strictly justify the features: - If DNA has “Long Text”, the domain must involve documents/logs/dialogue. - If DNA has “Images”, the domain must involve visual sensors. - If DNA has “Paired Categoricals”, the domain must involve matching/comparison. OUTPUT FORMAT: Return a JSON list of domains: [ { "domain": "Legal Tech", "scenario": "Contract Comparison", "justification": "feat_1/2 are Contract Types, feat_3/4/5 are Clause Text." }, { "domain": "E-Commerce", "scenario": "Product Duplicate Detection", "justification": "feat_1/2 are Categories, feat_3 is Title, feat_4/5 are Descriptions." } ] |
| You are a Data Simulation Engineer. I will provide the “Structural DNA” of a dataset. Your goal is to generate a “Mutation Config” that increases the difficulty of the task for an AI Agent. INPUT DNA: {dna_json} INSTRUCTIONS: 1. Detect Modality: (Image, Tabular, etc.) 2. Select 3 Corresponding Mutagens according to the modality and DNA: (Blur, Noise, Typos…) 3. Output Format: Return ONLY the JSON Mutation Config (the “patch”). EXAMPLE OUTPUT (for an Image Task): { "signal_mutations": [ {"type": "salt_pepper_noise", "amount": 0.05}, {"type": "rotation", "degrees": 45}, {"type": "class_imbalance", "ratio": "1:10"} ] } |
| You are a Synthetic Data Architect. You will receive an Abstract Data DNA (structural skeleton), a Target Domain (semantic context), and a Noise Configuration (difficulty modifiers). Goal: Merge these inputs to generate a Concrete Task Specification (New DNA). You must: 1. Concrete Mapping: Rename abstract features (e.g., feat_0 ) to realistic domain-specific names (e.g., systolic_blood_pressure ). 2. Apply Dimensions: specify the final row/column counts based on the constraints. 3. Embed Logic: Define the “Hidden Ground Truth Function” that relates the features to the target, incorporating the requested noise. Inputs Provided: 1. {{ORIGINAL_DNA}} : The JSON skeleton from the seed task. 2. {{SELECTED_DOMAIN}} : The industry context (e.g., “Healthcare: Triage”). 3. {{NOISE_CONFIG}} : The specific boosters (e.g., “Starvation Mode + Label Flipping”). Output Format: Return valid JSON only. The structure could be changed due to Tabular, Image, Text, Audio, or Graph data, depending on the original DNA.: { "task_name": "String (Creative Title)", "domain_context": "String", "final_dimensions": { "n_samples": Int, "n_features": Int }, "feature_mapping": { "feat_0": { "new_name": "String", "generation_logic": "String (distribution)" }, "feat_1": { "new_name": "String", "generation_logic": "String" } }, "hidden_rule_logic": "String (The mathematical formula: y = f(x) + noise, please do not be so simple, make it complex and realistic)", "evaluation_specs": { "metric": "String (same as original DNA)", "thresholds_logic": "String for Kaggle medal threshold (e.g. Gold = 0.90 (due to 10% noise). Silver = Random Forest baseline. Bronze = Linear Regression baseline. Median = Majority Class baseline.)" } } Constraints: * Speed Constraint: Keep n_samples to be a random number between 50 and 200. * Consistency: If the DNA says feat_1 is “High Cardinality”, map it to something like “ZipCode” or “PatientID”, not “Gender”. * Logic: The hidden_rule_logic must explicitly use the features you just named. |
| MLE Developer Prompt Template |
|---|
| You are an expert Python MLE Developer. You receive a Synthetic Task Blueprint (JSON) and must write one self-contained Python script named generate_task_env.py to build the training environment. Inputs: - Task DNA (JSON): includes modality (Tabular/Image/Text/Audio), final_dimensions , feature_mapping , and hidden_rule_logic . What your script must do: 1) Asset generation (deterministic, no external downloads): - Tabular: build DataFrames per the blueprint and save to train.csv and test.csv (test 20% the size of train). - Image: create images/ , draw synthetic images with Pillow or cv2 following the blueprint, save .png , and create train.csv and test.csv mapping filename to label (test labels blank but column present; schema matches train). - Audio: create audio/ , synthesize waveforms with numpy + scipy.io.wavfile (sine, noise, etc.), save .wav , and create train.csv and test.csv mapping filename to label (test labels blank but column present; schema matches train). - Text: if short texts, keep directly in train.csv / test.csv ; if long documents, save to docs/ as .txt and reference from train.csv / test.csv (schema matches). 2) Hidden rule logic: - Implement the blueprint’s hidden_rule_logic to assign labels deterministically. Be explicit about how features drive labels. 3) Heuristic leaderboard / sanity check: - Implement the threshold logic described in the blueprint (use its rules, ignore specific numeric targets). - Compute thresholds on the generated test data (per the threshold logic). - Save the computed thresholds in threshold.json with exactly these keys: "gold_threshold" , "silver_threshold" , "bronze_threshold" , "median_threshold" (values derived from the logic). 4) Sample submission: - Create sample_submission.csv with test IDs and a placeholder prediction column matching the target format; fill predictions with random or dummy values as examples. - Also create answer.csv containing the true labels for test data in the same format as sample_submission.csv (for hidden evaluation). Constraints: - Script must be standalone and runnable with common Python libs (numpy, pandas, Pillow/cv2, scipy). - Respect final_dimensions (n_samples/n_features/resolution) from the DNA. - Use informative comments where needed. Task DNA: {task_dna} |
| MLOps Engineer Prompt Template |
|---|
| You are an expert Python MLOps Engineer. Write a robust, standalone evaluation script named evaluator.py for this task. Task DNA (guidance for metric/dataset logic): {task_dna} Training data generator (use for consistent metric/threshold logic): {task_generator} Inputs to bake into the script: - Metric: choose the metric from the Task DNA/training data generator; hardcode its name and direction ( is_lower_better bool) in the script. Make sure the metric matches the code used in training data generator to derive the thresholds. - Medal thresholds (JSON): {thresholds_json} - Submission schema: {schema} Data layout: - Public folder contains sample_submission.csv (user submissions match this schema). - Ground truth is in answer.csv (relative to evaluator.py ). Script requirements: 1) Hardcode metric, direction ( is_lower_better bool), and thresholds at the top (derive metric/direction from Task DNA + schema). 2) CLI: accept --submission_path (default: sample_submission.csv ). 3) Load submission and ground truth, merge on id column if present; if no id, align by row order with a warning. 4) Compute the specified metric. 5) Output a JSON to stdout with keys: "score" , "gold_threshold" , "silver_threshold" , "bronze_threshold" , "median_threshold" , "is_lower_better" . Use the thresholds as given. 6) On any error, print a JSON error object to stdout (not stderr) and exit gracefully. 7) No external configs or downloads. Use only standard libraries plus numpy/pandas/sklearn if needed. 8) Emit pure Python: no markdown fences, no stray triple quotes. Ensure every string literal is closed and every dict/list is syntactically complete. |
| Technical Writer Prompt Template |
|---|
| You are a technical writer for synthetic ML benchmarks. Using the provided Task DNA, an example description from the seed task, the current contents of the public folder, and the data generator code, write a concise, clear description.md for this synthetic task. Keep structure and tone similar to the example but update names, data details, and task specifics to match the new Task DNA. Requirements: - Include an overview of the problem, data format, and evaluation metric. - Tell the users to generate the submission.csv file with predictions for the test set, consistent format with the sample_submission.csv . - Mention the sample_submission.csv schema explicitly so users know expected columns. - List the public data files by name (e.g., train.csv , test.csv , sample_submission.csv , images/* , audio/* , docs/* ) so users know what is provided. Do not include python files or answer.csv . - Keep the description to have the consistent structure with the example description. - Do not include Markdown code fences in the output; produce plain Markdown content only. Task DNA: {task_dna} Example description (seed task): {example_description} Public folder contents: {public_listing} Generator code (for reference on how files are created and what they mean): {generator_code} Sample submission schema: {sample_schema} |
LLM Agent Training
Large language model agent training teaches models to plan, use tools, and learn from multi-step interaction with environments.
See all 585 papers