Skip to content

The Lens

The Lens is the ordered list of output columns of a prism. It decides what answers holds in the default json format, the answer columns of a CSV, TSV or JSON Lines row, and the Lens columns the app shows on a result page, on the Integrate tab and in downloads. A prism has one Lens, and you edit it on the prism's Lens tab.

Until you save a custom one, a prism uses the automatic Lens, with one column per question named by the question key.

Question type Output support-routing column
Choice top team
Yes / No label urgent, Yes from 0.5
Scale level tone

The automatic Lens follows the prism, so a question added in a new version adds its column. Saving a custom Lens freezes the columns, so a new question adds nothing until you add a column for it. Reset to automatic goes back.

Each column reads one question and returns one output. The values below come from this stored answer, which format=raw returns:

format=raw
{
"id": "0192f5c1-7c1a-7b3e-9f55-3c1d2e4a5b6c",
"ref": "TCK-8812",
"prism": "support-routing",
"version": 3,
"status": "ok",
"error": null,
"took_ms": 640,
"created_at": "2026-09-23T09:14:02.187Z",
"answers": {
"team": {
"type": "choice",
"value": "billing",
"probabilities": {
"billing": 0.91,
"technical": 0.05,
"other": 0.03,
"insufficient_information": 0.01
},
"confidence": 0.88
},
"urgent": {
"type": "yes_no",
"probability": 0.83
},
"tone": {
"type": "scale",
"level": "annoyed",
"probabilities": {
"calm": 0.12,
"annoyed": 0.71,
"angry": 0.17
}
}
}
}
Type Output Returns json and jsonl
Choice top The chosen option "billing"
Choice probability The chosen option's probability 0.91
Choice all Every option's probability {"billing": 0.91, ...}
Yes / No label Yes, No or Unsure, from the column's cutoffs "yes"
Yes / No probability The probability of yes 0.83
Scale level The most probable level "annoyed"
Scale number That level's position, 1 for the lowest 2
Scale average The expected level number, to two decimals 2.05
Scale probability The most probable level's probability 0.71
Scale all Every level's probability {"calm": 0.12, ...}

CSV and TSV carry labels instead of keys, such as Billing, Yes and Annoyed, and an all cell reads Billing 0.91; Technical support 0.05; Other 0.03; Not enough information 0.01. Formats has the details. Probabilities are decimals from 0 to 1 in every format.

average is 1 × P(lowest) + 2 × P(next) and so on, so 0.12 × 1 + 0.71 × 2 + 0.17 × 3 = 2.05 here. It tells you where between the ends of the scale the answer sits, which level alone hides.

A Choice top whose stored value is null returns null, and so does its probability.

A column's name is the key in answers and the header in a CSV row. The default name is the question key, with _probability, _all, _number or _average added for extra outputs, such as team_probability.

Names are snake_case and unique. A column can't take a field key or one of the row names result_id, ref, version, status, error and created_at.

A label column turns the probability of yes into a word with two cutoffs:

  • no_below: below it, the answer is No.
  • yes_from: at it or above, the answer is Yes.

Between the two, the answer is Unsure. Without yes_from, Yes starts at no_below and there is no Unsure band. The automatic Lens uses no_below 0.5. no_below is strictly between 0 and 1. yes_from is at most 1 and above no_below, or above 0.5 when no_below is absent. The app's sliders set whole percents from 5% to 95%.

With no_below 0.4 and yes_from 0.6:

Probability of yes json csv
0.35 "no" No
0.4 "unsure" Unsure
0.59 "unsure" Unsure
0.6 "yes" Yes
0.83 "yes" Yes

An Unsure band is how you send the doubtful cases to a person instead of guessing.

Changing the Lens is not a new version and never asks the model again. Every read applies the current Lens to the stored answers, so a new cutoff relabels old results. If you raise yes_from to 0.9, the result above reads "urgent": "unsure" the next time you fetch it, from the API, the app or a download.

That is useful when you tune cutoffs against real results. It also means answers in json is not frozen. When a Lens edit must not change what your code reads, request format=raw, which returns the stored answers, and apply your own cutoffs. See Formats.

  • A result made by a version that lacks a column's question gets null for that column, or an empty cell.
  • Saving a prism version that removes a question drops the custom Lens columns that read it, in the same save. The app names those columns and warns first.
  • If a save drops every custom column, the prism falls back to the automatic Lens.
  • Renaming or removing a column carries the same warning.

Code that reads answers should expect a column to be missing or null rather than fail on it.

The support-routing examples in these docs use this Lens, which the app stores as JSON:

{
"columns": [
{ "name": "team", "question": "team", "output": "top" },
{ "name": "team_probability", "question": "team", "output": "probability" },
{ "name": "urgent", "question": "urgent", "output": "label", "no_below": 0.4, "yes_from": 0.6 },
{ "name": "tone", "question": "tone", "output": "level" },
{ "name": "tone_average", "question": "tone", "output": "average" }
]
}