Skip to content

Endpoint records to trace inputs

The endpoint records each call the way the platform sees it: the request, the response, and metadata around them. Trace processing wants one conversation per line instead. This page covers the download, the conversion, and the two files that go with the result.

distil inference-endpoint download-traces support-yeOdAS                  # newest 1000
distil inference-endpoint download-traces --count 5000 support-yeOdAS     # -c
distil inference-endpoint download-traces --all support-yeOdAS
distil inference-endpoint download-traces --file-name raw.jsonl support-yeOdAS

One record per line, written to <unique-endpoint-name>-traces.jsonl unless --file-name says otherwise. The platform pages the transfer itself, so --count caps what is kept, and --all walks every page within roughly the last 90 days.

Field What it holds
input The request body, as a JSON string: model, messages, and tools when the caller sent any
output The chat completions response, as a JSON string. The reply is choices[0].message
metadata.status The HTTP status the caller received
metadata.source Which model answered: fallback, or primary once a trained model fronts the endpoint
start_time, latency When the call started, and how long it took in seconds

The rest is identifiers and bookkeeping. Inspect one record before converting:

head -1 support-yeOdAS-traces.jsonl | jq '{
  status: .metadata.status,
  source: .metadata.source,
  request: (.input | fromjson | keys),
  reply: (.output | fromjson | .choices[0].message | keys)
}'

Per record: parse input and output, append the reply as the assistant turn to the request’s messages, carry tools across when present, and write one {"messages": [...]} object. Skip the records that shouldn’t become training data:

  • Failed calls. Keep metadata.status of 200 only.
  • Empty replies. Skip a response with neither content nor tool_calls, so no conversation ends on the user’s turn.
  • The wrong model’s answers, once a trained model fronts the endpoint. Filter on metadata.source to keep the fallback’s answers, the student’s, or both.
import json


def convert(record):
    if record["metadata"].get("status") != 200:
        return None
    request = json.loads(record["input"])
    reply = json.loads(record["output"])["choices"][0]["message"]
    if not reply.get("content") and not reply.get("tool_calls"):
        return None
    assistant = {"role": "assistant", "content": reply.get("content") or ""}
    if reply.get("tool_calls"):
        assistant["tool_calls"] = reply["tool_calls"]
    converted = {"messages": [*request["messages"], assistant]}
    if request.get("tools"):
        converted["tools"] = request["tools"]
    return converted


with open("support-yeOdAS-traces.jsonl") as src, open("traces-input/traces.jsonl", "w") as dst:
    for line in src:
        converted = convert(json.loads(line))
        if converted is not None:
            dst.write(json.dumps(converted, ensure_ascii=False) + "\n")

The reply can carry a reasoning field next to content when the fallback is a reasoning model. The conversion keeps content only, which is what your application used.

Check the kept count against the download and read the first few lines by eye. The result is a traces.jsonl in the default openai_messages format, so everything on Trace inputs applies to it from here.

traces-input/
├── traces.jsonl          # the converted records
├── job_description.json  # what the task is, in words
└── config.yaml           # task type, models, and a trace_processing section

The system prompt is in every record, because the endpoint saw the real request. Trace processing strips it from the traces, and expects its content in the job description’s task_description instead. Write that field from the system prompt your application sends, with the same care: the output format, the rules, the edge cases. Trace inputs covers the other fields.

config.yaml names the task type and the models. Pick the task type from what the traffic looks like, with Task selection: one user turn and one answer is question-answering or classification, a conversation with tool calls is one of the tool calling or chat completion tasks.

base:
  task: question-answering
  student_model_name: Qwen3-1.7B
  teacher_model_name: openai.gpt-oss-120b

trace_processing:
  observation_format: openai_messages

Upload the directory and process the traces into a seed dataset.