Skip to main content
Some questions only make sense after another one has been answered: ask whether a ticket is a sales lead only when it is not about billing, and rate the lead only when it is one. Three optional fields on every question type handle this: depends_on orders questions into stages, ask_if asks a question only when an earlier answer matches, and alone reads a question on its own. This page is for developers building question sets with follow-ups. Everything here happens inside one decision run and one model call. You do not chain requests yourself.

The three fields

They work the same on noul, choice and score questions.

A worked example

This set extends the ticket triage from the decision runs guide with two follow-ups:
  • sales_lead is asked only when bucket comes back other.
  • lead_value is asked only when sales_lead comes back yes.
triage-followups.json
When bucket comes back billing, as it does for this ticket, neither follow-up is asked. An abridged, illustrative decision part of the response, without draws, read, model, label_mass and answered_within_labels:

Stages and depends_on

A stage holds every question whose depends_on questions are all in earlier stages. Questions with no dependencies form the first stage. Within a stage, questions follow question_order, or sorted ids when you leave it out. The live response reports the schedule that ran in decision.stages. In the example, sales_lead depends on bucket, so it moves to the second stage, and lead_value depends on sales_lead, so it moves to the third.
  • Forward references are allowed. A question may depend on one that appears later in questions or in question_order. The schedule comes from the dependencies, not from the order you wrote them in.
  • No cycles. If a depends on b and b depends on a, directly or through other questions, the set is refused with 400 invalid_decision_questions: the questions depend on each other in a cycle.
  • No self-references. A question cannot name itself in depends_on or ask_if.
  • Only questions in the set. Every depends_on entry must be another question id in the same run.
When a question has an ask_if, list the question it names in depends_on as well, as the example does. The schedule is then explicit, and decision.stages shows the order you expect.

Gating with ask_if

ask_if maps a question id to the answer names that trigger this question:
The answer names you can list depend on the type of the question you name: A question set is refused with 400 invalid_decision_questions before anything is charged when: Note that a noul answers yes and no, not true and false. The true and false keys belong only to a noul question’s own criteria.

The skipped answer

When an ask_if condition is not met, the question’s answer is:
Skips cascade. In the example, sales_lead was skipped, so lead_value, which asks only when sales_lead is yes, is skipped too, and its because has no answered: there was no answer to compare.

Handle skipped answers in code

Every answer carries type, so check it before you read type-specific fields. A skipped answer has no probability, choice or score.

Reading a question alone

By default, the questions in one stage are read jointly. Set "alone": true on a question to read it on its own rather than jointly with the rest of its stage.

Limits that apply

Conditional fields do not change the run’s other limits:
  • 1 to 64 questions per run, skipped ones included.
  • The instructions, questions, draws and think_tokens together must fit in 32 KiB.
  • question_order, when you send it, must still name every question, including the ones that may be skipped.
  • The whole decision is one model call, whatever the number of stages.