Distilling Kimi-K3 into Qwen3-8B: a ~13× Agentic-SWE Gain, and Where It Plateaus

Cheng Luo — August 2026

How far can you push a small model as an agentic coder by learning from a giant's grader-verified traces? We distilled Kimi K3's software-engineering rollouts into Qwen3-8B, watched the gain scale cleanly with data — and hit both a data plateau and a genuinely hostile compute cluster along the way.

TL;DR

Teacher = Kimi K3 (Moonshot, 2.8T MoE) solving real GitHub-PR tasks (Scale-SWE-Verified) as a bash+edit agent. Student = Qwen3-8B. Method = offline SFT on only the grader-verified (reward==1) traces. On held-out, contamination-controlled tasks the distilled model beats base ~13–36× in-distribution (11.8% vs 0.9%; and up to 25.4% vs 0.7% on a fully self-collected run), scaling monotonically with data and saturating around ~360 traces. The direction holds on an independent benchmark (swebench_verified), and reproduces with zero dependence on external data.

Why offline SFT trace-distillation

K3 is a black-box API — no logits — and at ~1.4 TB it can't be self-hosted on the GPUs we had, so white-box on-policy distillation is out. The offline route is simple and robust:

  1. Let K3 solve agentic SWE tasks inside the eval harness (docker sandbox, bash + edit tools), producing full multi-turn rollouts with its chain-of-thought.
  2. Keep only the rollouts the grader marks correct (reward==1) — a free quality filter.
  3. SFT the student on those traces (loss-masked to assistant turns; K3's reasoning kept as <think> via the Qwen3 renderer).
  4. Evaluate the student vs. base on held-out tasks under the same harness.

Teacher and student share the exact system prompt and tool schema, so there is no harness-mismatch confound — the student learns to imitate K3 in the same interface it's later judged in.

The pipeline

The result: it works, and it scales

The full loop, run at four data scales. In-distribution pass@1 (held-out, dedup'd against trained tasks):

# tracesdistilled vs base (scaleswe held-out)verdict
31~0% vs ~4%no effect — pure noise
1635.0% vs 0.7%~7×
36011.8% (13/110) vs 0.9% (1/115)~13×, p<0.001
718~8–10% vs ~2%plateau
454 (self-collected only)25.4% (36/142) vs 0.7% (1/141)~36×, large sample

The 360-trace run mixed in traces from a parallel collector, so as a clean-provenance check we re-ran the whole loop on 454 traces we collected entirely ourselves (all verified kimi-k3; the two sources are statistically indistinguishable in reasoning density, trace length, and tool-call count). On a full n=142 held-out sample it gave the strongest, cleanest result of the project: 36 solved vs the base model's 1. The conclusion holds — if anything more strongly — with zero dependence on external data.

Two things make the 360 result trustworthy rather than a lucky benchmark:

  1. Statistical separation. 13 solved vs 1 solved out of ~110 tasks each — a Fisher test puts this well under p=0.001. The 31-trace pilot showed nothing; the effect emerged and grew with data.
  2. Cross-benchmark agreement. On swebench_verified — a separate benchmark with no task overlap and no contamination — the distilled model still leads (7.9% vs 4.3% at 163; 4.3% vs 2.1% at 360). Same direction, independent data.

And then it plateaus. Pushing to 718 traces (407 distinct tasks, ~2× the data) did not clearly beat 360 across three eval attempts. More agentic traces beyond a few hundred bought no further generalization here.

Interpretation. A few hundred grader-verified agentic traces are enough to teach a small model the shape of the work — reason, call bash, read output, edit, iterate — and that transfers to a real, significant capability gain. Beyond that, the bottleneck stops being "has it seen enough good trajectories" and becomes the 8B model's own ceiling.

The real adversary: infrastructure

Honestly, the model work was the easy part. The hard part was the environment.

Kimi's upstream is diurnal. Single calls always worked, but heavy concurrent agentic requests (20k-token prompts, long reasoning) hit gateway 503/504s during Moonshot's night. Our first high-concurrency run was a disaster: 68% of rollouts errored, ~$293 for 76 usable traces. The clean fix was a self-gating auto-collector that probes K3 health every 15 minutes and only collects during healthy windows, pausing itself (and the spend) when the upstream degrades.

The GPU cluster reclaims aggressively. Long training and serving jobs got SIGTERM'd within tens of minutes, seemingly at random — corrupting checkpoints mid-write (AssertionError: metadata is None). We lost a perfect 3.5-hour run to a reclaim during the final save. The fix that finally worked:

[ckpt]
interval = 45          # checkpoint frequently
weights_only = true    # skip the heavy optimizer-state gather -> fast, atomic-ish writes
Frequent, weight-only checkpoints mean a reclaim can never cost more than one interval — you always have a recent, complete, servable model. A serving corollary: 24 concurrent 40k-token rollouts OOM the KV cache and 500, so eval concurrency has to stay low.

Lessons

  1. Grader-verified filtering is a fantastic free signal. No reward modeling, no preference data — just "did the tests pass," and the surviving traces are gold.
  2. A few hundred good agentic traces go a long way — and then diminishing returns hit fast. Measure the scaling curve; don't assume more is better.
  3. Measure like you mean it. Held-out + dedup against every trained task + an independent second benchmark. A single benchmark at n=24 is noise.
  4. On a hostile cluster, make everything resumable and self-healing. Frequent weight-only checkpoints, health-gated collection, server watchdogs. The infra harness mattered as much as the ML.
  5. A tiny, well-placed piece of glue (the round-robin proxy) can be the difference between a run that dies and one that finishes.

Bottom line

Distilling Kimi K3's grader-verified agentic SWE traces makes Qwen3-8B a meaningfully, statistically-significantly better software-engineering agent — about 13× in-distribution pass@1 over the base model — with the gain scaling cleanly from a handful of traces up to ~360, then saturating. The teacher's API and the compute cluster fought us the whole way; the winning move was building infrastructure resilient enough to let the (surprisingly data-efficient) science come through.