TikTok TechJam 2026 · Track 2 · KuaiRand-Pure

387 experiments.
10 of them worked.

An autonomous agent ran the machine-learning research loop — measure, diagnose, invent, implement, verify, decide — across 21 runs with zero manual interventions. This is every experiment it ran, including the ones that failed and the guards that caught them.

387Experiments
10Accepted
0.6038Best unaided, 20-seed
102Stopped before training
4.9CPU-core-hours, 0 GPU
0Manual interventions
The result

What was submitted

The validation-best checkpoint at convergence, measured over 20 seeds, then scored once on the hidden test split after the configuration was frozen. Test was unreachable during the search, so no selection decision could be contaminated by it.

splitGAUCnDCG@5primarybaseline primaryscore_dataset
validation, 20-seed mean0.67020.53730.60380.6016+0.0022
hidden test, scored once0.66390.53040.59720.5946+0.0026

The gain held on test and grew slightly. Validation sd over 20 seeds is 0.0003 and all 20 seeds beat the baseline. The run converged in 5 research cycles of the 50 permitted, logging 13 experiments once its 8 exploit trials are counted, on 105,304 tokens and 59 minutes of wall-clock with zero manual interventions.

The search

Every experiment, every run

One cell per experiment, ordered as it happened. Most were caught before they cost a training run: a patch that reads as the intervention and changes nothing is the most common failure here, and it is detected in 0.4 seconds.

acceptedtrained, revertedblocked by contractcrashedexploit trialno problem named
V1 01-library-pipeline-20
V2 02-clean-replay-librar
V3 03-classify-pipeline-2
V4 04-tier1-smoke-6cyc
V4 05-autonomy-benchmark-
V4 06-clean-run-14cyc
V5 agent_derive
V6 final
V4 run07
V5 v5
V5 v5_exploit
V5 v5_exploit2
V6 v6
V6 v6b
V6 v6c
V6 v6c_gpt55
V6 v6c_verify
V7 v7
V7 v7b
V8 v8
V8 v8b
Results

Where each accepted result landed

The official baseline is 0.6016 and the oracle ceiling is 0.8484: 27.1% of evaluation users have no positive label, so their nDCG is zero for any model. Total headroom is 0.247, and the organisers’ own ablations move this metric by less than 0.002. Everything below sits inside a 0.004 window.

0.6038 human 0.6016 baseline 0.6014 start V4 05-autonomy-benchmark-21cyc: 0.6022 — temporal-decay-relevance0.6022V4 V4 06-clean-run-14cyc: 0.6031 — weighted-loss-imbalance0.6031V4 V5 agent_derive: 0.6022 — temporal-decay-weights0.6022V5 V6 final: 0.6023 — curriculum-learning0.6023V6 V6 final: 0.6040 — length-normalization0.6040V6 V4 run07: 0.6028 — temporal-patterns0.6028V4 V5 v5_exploit: 0.6014 — user-cluster-features0.6014V5 V6 v6: 0.6031 — class-weighted-loss0.6031V6 V6 v6c: 0.6022 — temporal-activity-features0.6022V6 V6 v6c_gpt55: 0.6030 — focal-loss-weighting0.6030V6

The best of these measures 0.6038 over 20 seeds (sd 0.0003), which matches the human-tuned result exactly — by a different route. The human path was a listwise objective trained on evaluation-length lists plus a retuned learning rate; the agent reached the same score through curriculum learning over sequence length and a length-normalisation feature. It did not rediscover the human path.

Why the accept margin exists

The win that wasn’t

An exploit trial measured a clear improvement on the first seed. Run on five seeds, it averaged to almost nothing. The keep/revert decision is arithmetic, not a judgement call, and it declined.

accept margin 0.0008seed 0 only+0.0012mean of 5 seeds+0.0004

The gate was right. A human looked at the same numbers and spent an hour chasing it.

The same rule applied in the other direction on the final run. An accepted result read 0.6040 on one seed, and a neighbouring configuration in the same sweep read 0.6040 and measured 0.6034 across five. So it was tested at 20 seeds before anything was claimed: mean 0.6038, sd 0.0003, every seed above the baseline. The caution was right to apply, and this time the result survived it.

Where the effort went

The model never changed

The scoring function is a factorisation machine throughout, the same architecture as the official baseline. Every accepted improvement came from the training objective or the input features. 35 experiments edited the model and none of them was accepted.

ModuleExperimentsShareWhat it controls
train.py18051%objective, optimiser, batching
features.py13539%what the model sees
model.py3510%the scoring function itself

Every accepted result

PrimaryModuleTechnique
0.6040features.pylength-normalization
0.6031train.pyweighted-loss-imbalance
0.6031train.pyclass-weighted-loss
0.6030train.pyfocal-loss-weighting
0.6028features.pytemporal-patterns
0.6023train.pycurriculum-learning
0.6022features.pytemporal-decay-weights
0.6022features.pytemporal-decay-relevance
0.6022features.pytemporal-activity-features
0.6014features.pyuser-cluster-features
The one it could not land

50 attempts, 0 accepted

The human improvement came from training the ranking objective on lists the length of the evaluation lists. The agent reached for that same family — listwise objectives, group sizing, list-length handling — in 50 experiments across the project, and 0 were accepted. It repeatedly identified the right mechanism and never made it work, while every win it did land came from somewhere else.

Diagnosis was never the bottleneck. Selection and implementation were.

Architecture

Every generation, including the ones that failed

Each generation added a stage in response to a measured failure of the last. Two were built, measured, and reverted.

GenRunsImprovedExperimentsBest
V11020
V21025
V31025
V443610.6031
V542680.6022
V6641100.6040
V72048
V82030
Cost

Where the tokens go

Five roles, each on the model it needs. The judge writes only prose because its verdict is arithmetic; the coder is the measured bottleneck and the largest single cost.

RoleTokensShareJob
coder1752K47%write correct numpy
inventor913K24%propose interventions
classifier723K19%name the problem
analyst295K8%pick tools, report numbers
reflector51K1%explain a decision already made

4.9 GPU-hours across 10.1 hours of wall clock, on a laptop CPU with no accelerator. numpy and pandas only.

Run ledger

Every run, reported in full

Including the architecture generations that were built, measured, and reverted because they did not produce a win.

RunArchExpsContract sat.KeepsBestTokensStopped
01-library-pipeline-20cycV120100%0159Kmax_iterations
02-clean-replay-library-25V225100%0223Kmax_iterations
03-classify-pipeline-25cycV325100%0214Kmax_iterations
04-tier1-smoke-6cycV460%059Kmax_iterations
05-autonomy-benchmark-21cyV42142%10.6022267Kconverged
06-clean-run-14cycV41464%10.6031143Kconverged
agent_deriveV52361%10.6022207Kconverged
finalV61392%20.6040105Kconverged
run07V42050%10.6028228Kconverged
v5V53045%0303Kmax_iterations
v5_exploitV5783%10.6014
v5_exploit2V5857%082Kmax_iterations
v6V61660%10.6031166Kconverged
v6bV62125%0307Ktoken_budget
v6cV62288%10.6022247Kconverged
v6c_gpt55V61362%10.6030146Kconverged
v6c_verifyV62581%0313Kmax_iterations
v7V72385%0307Ktoken_budget
v7bV72586%0286Kmax_iterations
v8V85100%0
v8bV82540%0466Kmax_iterations