Skip to main content
End-to-end instructions for collecting high-quality rollouts and turning them into JSONL datasets for Synth SFT training.

1. Prepare Your Task App

  1. Write or pick a TaskAppConfig (a .py file that registers your app in synth_ai.task.apps.registry).
  2. Create an .env file containing at least:
    ENVIRONMENT_API_KEY=...
    SYNTH_API_KEY=...
    
    Use synth-ai setup or a password manager to keep these up to date.
  3. Sanity-check the app (optional but recommended). Export TASKAPP_SFT_OUTPUT_DIR=traces/sft_records, then run uvx synth-ai deploy ... with whichever runtime you plan to use (local for iteration, Modal for shared collectors). Stop here if the app fails; SFT data collection depends on a healthy task app.

2. Deploy for Rollouts

Pick the runtime best suited for the collection session:
  • Local (--runtime local): fastest iteration while you develop. Tracing is auto-enabled; set TASKAPP_SFT_OUTPUT_DIR to choose where JSONL batches land.
  • Modal (--runtime modal): deploys to Modal so teammates can collect rollouts or run larger batches. Provide --modal-app (and optionally --name) to map to your entrypoint.
# Local dev
uvx synth-ai deploy \
  --task-app task_apps/my_app.py \
  --runtime local \
  --env .env

# Modal (shared collection)
uvx synth-ai deploy \
  --task-app task_apps/my_app.py \
  --modal-app task_apps/my_app_modal.py \
  --runtime modal \
  --env .env \
  --name my-app-prod

3. Collect Rollouts with Tracing Enabled

Rollouts are what power SFT. You can gather them manually, via automation, or by sharing the task app with labelers:
  1. Confirm tracing is still on. Local deploys run with --trace enabled by default, so TASKAPP_TRACING_ENABLED=1. You must set TASKAPP_SFT_OUTPUT_DIR (or SFT_OUTPUT_DIR) yourself before launching if you want JSONL written to disk.
  2. Point your collector at the task app. Common options:
    • uvx synth-ai eval ... --url <TASK_APP_URL> to run scripted rollouts.
    • Custom agents or labeler tools hitting /rollout and /states.
  3. Run enough variety. Aim for dozens to hundreds of sessions that demonstrate the behaviors you care about.
  4. Verify traces exist: Inspect the directory you pointed TASKAPP_SFT_OUTPUT_DIR at to make sure JSONL batches are appearing.

4. Export SFT JSONL with synth-ai filter

Once you have traces, convert them into training examples:
  1. Write a [filter] TOML describing where to read from and where to write:
    [filter]
    db = "traces/trace_records.db"
    output = "ft_data/my_app_sft.jsonl"
    splits = ["train"]
    min_official_score = 0.5
    min_judge_scores = { "accuracy" = 0.7 }
    limit = 500
    
  2. Run the filter command:
    uvx synth-ai filter --config configs/filter-my-app.toml
    

5. Validate the Dataset Before Training

Run the CLI in validation-only mode so schema issues surface before you launch a full job:
uvx synth-ai train \
  --type sft \
  --config configs/sft/my_app.toml \
  --dataset ft_data/my_app_sft.jsonl \
  --no-poll
Fix any reported rows (missing roles, malformed tool payloads, etc.) and rerun until the command exits cleanly.

6. Next Steps: Train with synth-ai train --type sft

With a validated JSONL, you can update your SFT config to point at the new dataset (or pass --dataset to the CLI) and launch training:
uvx synth-ai train \
  --type sft \
  --config configs/sft/my_app.toml \
  --dataset ft_data/my_app_sft.jsonl \
  --env .env
See Generate Training Data for complete documentation.