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.
Download the records
Section titled “Download the records”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.
What a record holds
Section titled “What a record holds”| 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)
}'
Convert to conversations
Section titled “Convert to conversations”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.statusof 200 only. - Empty replies. Skip a response with neither
contentnortool_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.sourceto 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.
The two files that go with it
Section titled “The two files that go with it”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.