1. Tasks
  2. System One Model Call

Tasks

System One Model Call

Evaluates a state against one or more structured questions using a System One model. Returns typed judgments — choices, scores, and probabilities — that can be used directly in automation logic.

Unlike a general-purpose LLM call, System One models do not generate free-form text. Each question produces a structured, typed answer with a confidence score, making the results directly usable in task logic without parsing or prompting.

See Models for a full list of supported System One models.

Use cases

  • Route an inbound message to the correct department based on its content.
  • Score customer sentiment or urgency before deciding which workflow to trigger.
  • Verify that a piece of text meets a condition before continuing a process.
  • Pick the best match from a long list, such as a contact list, product catalogue, or knowledge base.
  • Evaluate documents too long for a single model call.

Basic usage

loading...

Parameters

model
required
string

The System One model to use. Currently supported:

See Models for a full list of supported models.


state
required
string | object | array

The content for the model to evaluate. All questions in the request see the same state.

Format Useful for Example
String A message, article, or passage "My card was charged twice."
Object Named fields, related records, or application state {"message": "My card was charged twice.", "order_id": "A-104"}
Array A sequence of messages or records ["Hi", "My customer number is TS1337.", "My card was charged twice."]

State must contain text only. Images, audio, and video are not supported.

An object or array state is always sent exactly as given. Only a string state can be chunked (see data_processing.state.auto_chunk_large_text_states_into_multiple_calls).


questions
required
object

An object of named questions to evaluate against the state. Each key becomes the corresponding key in response.answers. All questions are evaluated independently in one request.

Each question has a type that determines its structure and the shape of its answer.


questions[name].type
required
string

The question type. One of noul, choice, or score.


questions[name].instructions
required
string

A natural language description of what the model should evaluate.


questions[name].criteria
object | array | string

Defines the valid answer space for choice and score questions. Not used for noul questions.

For score: an array of strings describing each point on the scale, ordered from lowest to highest.

For choice: the options the model can pick from. A choice question accepts up to 255 options, or more with auto_split_on_max_choices. The options can be given in any of these formats:

Format Example Option keys
Object {"billing": "Payment or subscription issues"} Used as given
Array ["Good Afternoon", "Good Morning"] good_afternoon, good_morning
Comma or line separated "Billing, Technical Support, Sales" billing, technical_support, sales
CSV text See CSV criteria row_001, row_002, …

An object is the most precise format: each key is a valid answer and each value describes it.

For arrays and separated strings, the key for each option is generated from its text:

  • The text is lowercased, accents are removed, and anything other than letters and numbers becomes _. For example, "Café Crème!" becomes cafe_creme.
  • Keys that would clash get a number: "Good Afternoon" and "good afternoon!" become good_afternoon and good_afternoon_1.
  • Values that aren't text are converted to text first. Empty values are skipped.
  • The original text becomes the option's description, and is returned in choice_criteria_value.

A string is split on commas and line breaks, unless it's marked as CSV with criteria_is_csv.


data_processing
object

Optional processing applied before and after the model call. Use it to chunk long state, split long option lists, and add convenience fields to answers.

data_processing is never sent to the model.

loading...

data_processing.state.auto_chunk_large_text_states_into_multiple_calls
boolean

When true and the state is a string too long for one model call, the state is split into chunks and every chunk is evaluated against the same questions. The response then contains one set of answers per chunk (see response.chunks).

  • The size limit takes the questions into account: the longer the questions, the less room is left for state.
  • Text is split at paragraph breaks where possible, then line breaks, sentences, and finally words.
  • Chunks don't overlap.
  • A state that fits in one call is evaluated normally, and the response has its usual shape.
  • If the questions alone leave too little room for any state, the task returns an error asking you to reduce the number or size of the questions.

Default: false.


data_processing.state.state_is_csv
boolean

Marks a string state as CSV text. When the state has to be chunked, it's split between rows instead of at paragraph breaks, and the header row is repeated at the top of every chunk so each chunk can be understood on its own.

Each chunk is still sent as a single string. Has no effect unless auto_chunk_large_text_states_into_multiple_calls is true and the state is too long for one call.

Default: false.


data_processing.questions.choice.auto_split_on_max_choices
boolean

When true, a choice question with more options than set_max_choices is split into several questions named after the original with a number appended: article becomes article_1, article_2, and so on.

  • Options are shared out evenly: 300 options with a maximum of 255 become two questions of 150.
  • Each split question keeps the original instructions.
  • The response lists the split question names in response.split_questions.

Each split question picks its best option from its own share of the options only, so its probabilities can't be compared directly with those of the other split questions. To get a single answer across all options, also set auto_final_round_on_split.

Default: false.


data_processing.questions.choice.set_max_choices
integer

The most options a single choice question may have before it's split. Must be between 3 and 255.

Default: 255, or 20 for CSV criteria.


data_processing.questions.choice.auto_final_round_on_split
boolean

When true, the best options from each split question are asked again together in a final round. The winner is returned under the original question name, with a final_round field added.

For example, with 300 options split into article_1 and article_2, the top 5 options of each are asked again as one 10-option question, and its answer is returned as article.

  • If the combined options still exceed set_max_choices, they're split and asked again until one question remains.
  • The split answers (article_1, article_2, …) are still included in the response.
  • Each round is an extra model call, and its tokens are added to usage.

Default: false.


data_processing.questions.choice.final_round_candidates_per_split
integer

How many of the best options from each split question go through to the final round. A split question never contributes more than half its options, so each round at least halves the field.

Default: 5.


data_processing.questions.choice.return_top_n
integer

Adds choices_top_n to every choice answer: the n most likely options, from most to least likely.


data_processing.questions.choice.criteria_is_csv
boolean | array

Marks string criteria as CSV text instead of a comma or line separated list.

  • true: every choice question with string criteria is treated as CSV.
  • An array of question names, e.g. ["contact"]: only those questions are treated as CSV. Each named question must be a choice question with string criteria.

See CSV criteria for how the rows become options.

Default: false.


data_processing.questions.noul.return_noul_as_boolean_on_threshold
number

Adds noul_boolean to every noul answer: true when noul is at or above this threshold, otherwise false. The noul probability itself is left unchanged. Must be between 0 and 1.

Raise the threshold when a false true is costly, and lower it when missing a true is costly.

CSV criteria

With criteria_is_csv, a choice question can take a spreadsheet-style list of options, such as a contact list or product catalogue, exported as CSV text.

editor
        "criteria": "name,department,city\nAlice Smith,Billing,Cape Town\nBob Jones,Sales,\"Durban, KZN\""

      

How the text is read:

  1. The first row is the header. It names the columns. An empty column name is replaced by its position (an empty second column becomes column_2), and repeated names get a number (name, name_1).

  2. Every other row becomes one option, keyed row_001, row_002, … in order. With more than 999 rows the numbers get wider (row_0001).

  3. Each option's description is the row, labelled by column. The example above becomes:

    loading...
  4. The separator is detected from the header row: comma, semicolon, or tab.

  5. Standard CSV quoting is supported. A value in double quotes can contain the separator or line breaks, and "" inside quotes is a literal quote.

  6. Blank rows and empty cells are left out. A row with an empty city simply has no city field.

  7. CSV questions are split at 20 options by default, even without auto_split_on_max_choices, because each row is a full record. Set set_max_choices to change this, and auto_final_round_on_split to get a single winner.

The model answers with a row key such as row_002. The full row is returned in choice_criteria_value, so you can use answers.contact.choice_criteria_value.name directly.

The CSV must have a header row and at least one data row, otherwise the task returns an error.

Result

loading...

Properties

response.model
string

The resolved model version that processed the request.


response.answers
object

An object keyed by each question name provided in questions. Each answer's shape depends on the question type.

When choice questions are split, the split answers (name_1, name_2, …) appear here too, and with a final round the combined answer appears under the original name.


response.answers[name].noul
number

For noul questions. A float between 0 and 1 indicating the probability that the condition described in instructions is true.


response.answers[name].noul_boolean
boolean

For noul questions, when return_noul_as_boolean_on_threshold is set. true when noul is at or above the threshold.


response.answers[name].choice
string

For choice questions. The key from criteria that the model selected.


response.answers[name].choice_criteria_value
string | object

For choice questions. The description of the selected option from criteria. For array and list criteria this is the original text ("Good Afternoon" rather than good_afternoon); for CSV criteria it's the full row object.


response.answers[name].choices_top_n
array

For choice questions, when return_top_n is set. The most likely options, from most to least likely:

editor
        "choices_top_n": [
  { "choice": "technical", "probability": 0.83, "criteria_value": "Bugs or integration problems" },
  { "choice": "billing", "probability": 0.17, "criteria_value": "Payment or subscription issues" }
]

      

response.answers[name].final_round
object

For the combined answer of a split choice question, when auto_final_round_on_split is set. Contains rounds, the number of model calls it took including the first, and candidate_count, the number of options in the last round.


response.answers[name].confidence
number

For choice and score questions. A float between 0 and 1 indicating the model's confidence in its answer.


response.answers[name].probabilities
object

For choice and score questions. The full probability distribution across all options.


response.answers[name].score
number

For score questions. The position on the scale defined in criteria, from 0 to the highest level. It's a weighted average of the levels, so it can fall between them: 1.43 on a 0–2 scale leans between the second and third levels. Use score_level for a whole level.


response.answers[name].score_level
integer

For score questions. The zero-based index of the most likely level.


response.answers[name].score_criteria_value
string

For score questions. The label from criteria for score_level.


response.answers[name].legend
object

For score questions. Maps each score index back to the label from criteria for easy reference.


response.values
object

A flat summary of every answer, keyed by question name, for easy use in templates:

  • noul: noul_boolean when a threshold is set, otherwise the noul probability.
  • choice: the selected key.
  • score: the score.

response.split_questions
object

Present when choice questions were split. Maps each original question name to its split question names, e.g. {"article": ["article_1", "article_2"]}.


response.chunks
array

Present when the state was chunked. response.chunked is true, and response.answers and response.values are replaced by one entry per chunk, in order:

loading...
  • state_range is the character range of the original state that the chunk covers. With state_is_csv, the range covers the chunk's rows; the header row sits at the start of the state.
  • estimated_state_tokens is an estimate, because the model's exact token count isn't known in advance.
  • usage on each chunk is that chunk's own usage.

response.usage
object

Token usage for the request. Contains input_tokens and output_tokens. When the task makes more than one model call (chunks or final rounds), this is the total across all of them.


Examples

Routing and sentiment in one call

Evaluate urgency, department routing, and frustration level together in a single request.

loading...

Structured state

Pass related context as an object so the model can evaluate the full picture.

loading...

Yes/no answers as booleans

Get true or false directly instead of a probability. Read the result from response.values.is_urgent or response.answers.is_urgent.noul_boolean.

loading...

Simple option lists

Give choice options as an array or a comma separated string when they don't need descriptions. The keys are generated for you.

loading...

The answers use the generated keys, e.g. "choice": "technical_support", with the original text in choice_criteria_value.

Pick a contact from a CSV list

Match a message to the right person in a contact list. The list is split into questions of 20 rows, and the best 5 rows from each go through to a final round.

loading...

The chosen row is in response.answers.contact.choice_criteria_value, e.g. {"name": "Bob Jones", "department": "Sales", "city": "Durban, KZN"}, and the three closest matches are in choices_top_n.

Evaluate a long document

Check a document that may be too long for one call. Each chunk is evaluated separately, so you can see which parts of the document matched.

loading...

If the document is long enough to be chunked, check response.chunked and read each chunk's values. Otherwise, the answer is in response.values as usual.