Traffic
Import files
Upload a file of past production conversations, and one of their outcomes, to build the migration report with no integration. Every line is checked first; a file is stored whole or not at all.
#Conversations (JSONL)
On the agent's Traffic, Add conversations, Import a file, then Import JSONL, or POST /api/agents/<agent uid>/conversation-imports?filename=<name> with the file as the body. Each line is one whole, ended conversation in OpenAI Chat Completions format (pretty-printed here; in the file it is one line). Download the example file: three invented conversations.
{"external_id": "nw-1001", "started_at": "2026-10-20T14:02:11Z", "user_id": "cust_0042",
"model": "gpt-5.4-mini", "metadata": {"channel": "chat"},
"tools": [{"type": "function", "function": {"name": "get_booking", "parameters": {"type": "object",
"properties": {"code": {"type": "string"}}, "required": ["code"]}}}],
"messages": [
{"role": "system", "content": "You are Ava, the support agent of Northwind Rentals."},
{"role": "user", "content": "Hi, can you move booking NW-7731 to Friday?"},
{"role": "assistant", "content": null, "tool_calls": [{"id": "call_1", "type": "function",
"function": {"name": "get_booking", "arguments": "{\"code\": \"NW-7731\"}"}}],
"usage": {"prompt_tokens": 412, "completion_tokens": 18,
"prompt_tokens_details": {"cached_tokens": 0}}},
{"role": "tool", "tool_call_id": "call_1", "content": "{\"status\": \"confirmed\"}"},
{"role": "assistant", "content": "Done: NW-7731 now starts Friday.",
"usage": {"prompt_tokens": 468, "completion_tokens": 21}}]}external_id- Required: your conversation id, up to 200 characters, unique per agent. Outcomes name it. An id the agent already has, or that another line of the file repeats, refuses the file.
started_at- Required: when it started, ISO 8601 with a UTC offset.
messages- Required, in order:
systemordeveloper(the instructions),user,assistant(content,tool_callsor both) andtool(tool_call_idandcontent, the call's result).contentis a string or a list oftextparts;nameis allowed. Every tool call must be answered by a later tool message, and every tool message must answer an earlier call. Each answered call becomes a tool turn, statusexecuted, where its answer is. tools- Optional: the agent's tools as Chat Completions definitions (
{"type": "function", "function": {name, description, parameters}}). With the system messages they are the conversation's config snapshot, so the judge cites the rules and tools it ran with; then every called tool must be one of them. Tools without a system message are refused. Without a system message there is no snapshot, as for conversations sent withoutconfig. model- Optional: the model the agent ran on, as your code calls it. It goes into the snapshot and prices
usage. usage- Optional, on an assistant message: the usage object of the Chat Completions response that wrote it (
prompt_tokens,completion_tokens, optionallytotal_tokens,prompt_tokens_details.cached_tokensand the other token details). It needsmodel, and lands on the message's text turn, else on its first answered call; see Cost. user_id,metadata- Optional: a pseudonymous user id, and string values only.
Any other field is refused. Imported conversations are stored ended, in the production environment (an API key's own environment when it imports), redacted like every conversation, judged like the ones you send, and marked with their import: the conversation's details name the file, and the list's imported filter (the import's uid) shows one import's conversations. The migration report reads the last 30 days of traffic by started_at, so import conversations that started within them.
#Errors
Nothing is stored until every line is valid. A refused file answers 422 with every error, line by line: {"detail": {"errors": [{"line": 4, "field": "messages.2.tool_calls.0.id", "reason": "no tool message answers this call"}], "total": 1}}. line is 1-based as editors number lines, field the path inside the line (null for the line as a whole: not JSON, blank, over the limit), and the first 200 errors are listed with total counting them all. Traffic shows the same table under the button. Fix the file and import all of it again.
#Outcomes (CSV)
Declare the outcomes first (Traffic, Outcomes), then From a CSV file, or POST /api/agents/<agent uid>/outcome-imports with the file as the body. The header names these six columns, each once, in any order; download the example file.
conversation,id,name,occurred_at,value,currency nw-1001,evt-5001,booking_kept,2026-10-23T10:00:00Z,, nw-1002,evt-5002,refunded,2026-10-22T12:30:00Z,350.00,USD
conversation- The conversation's
external_id: one the agent has, imported or sent. id- Your event id, unique per agent: importing it again replaces the event, so a file imported twice counts once. Repeated in one file, it is refused.
name- One of the agent's declared outcomes.
occurred_at- ISO 8601 with a UTC offset, not before the conversation started.
value,currency- A money outcome's amount and its declared currency; both empty for an outcome without value.
Each row is checked as a sent outcome is, and the file is stored whole or refused with each row's line and reason (the header is line 1).
#Limits
- A conversations file: at most 10 MB and 5,000 conversations, each line at most 1 MB.
- An outcomes file: at most 2 MB and 10,000 rows.
- Larger files answer 413 (over the size) or a refusal at the first line past the count: split them and import each part.
- Each import counts as one ingest request against the workspace's 1200 a minute.