Skip logic & conditions
Control survey flow based on respondent answers. Flashpoint.AI uses a single DSL (domain-specific language) for display conditions, skip rules, quota definitions, and variable assignments. Learn the DSL once, use it everywhere.
DSL syntax reference
Conditions are strings evaluated at runtime against the respondent's answers. Question labels (e.g., Q1, Q3) resolve to the respondent's answer for that question.
Operators
| Operator | Syntax | Description |
|---|---|---|
| Equals | Q1 == `2` | True if Q1's selected option label is 2 |
| Not equals | Q1 != `2` | True if Q1's selected option label is not 2 |
| Greater than | Q1 > 18 | Numeric comparison |
| Greater or equal | Q1 >= 18 | Numeric comparison |
| Less than | Q1 < 18 | Numeric comparison |
| Less or equal | Q1 <= 18 | Numeric comparison |
| In list | Q1 IN [`1`, `2`, `3`] | True if Q1's answer is in the list |
| Not in list | Q1 NOT IN [`4`, `5`] | True if Q1's answer is not in the list |
| And | (Q1 == `1`) AND (Q2 > 5) | Both conditions must be true |
| Or | (Q1 == `1`) OR (Q2 == `1`) | Either condition must be true |
| Not | NOT (Q1 == `1`) | Negation |
| Xor | (Q1 == `1`) XOR (Q2 == `1`) | Exactly one must be true |
Value syntax
- Option labels are wrapped in backticks:
`1`,`2`,`3` - Numeric literals are bare:
18,100,3.5 - Strings use quotes:
"complete",'active' - Boolean literals:
TRUE,FALSE - Null:
NULL - Logical operators are always uppercase:
AND,OR,NOT,XOR,IN,NOT IN
Identifiers
An identifier is a question label that resolves to the respondent's answer:
| Pattern | Resolves to |
|---|---|
Q1 | Single-select: the selected option. Multi-select: array of selected options |
Q3\Row1 | Grid response: the column selected for Row1. Backslash separates row label |
STATUS | Current response status string (e.g., "COMPLETE") |
Multi-select behavior
For multi-select questions, == checks array containment (whether the value is among the selections), not strict equality. IN checks whether any selected option is in the list.
Q5 == `3` -- true if option 3 is among the selected options
Q5 IN [`1`, `2`, `3`] -- true if ANY of the selected options is 1, 2, or 3
Q5 NOT IN [`4`, `5`] -- true if NONE of the selected options is 4 or 5
Aggregate functions
Use with list operands for computed conditions:
| Function | Example | Description |
|---|---|---|
COUNT | COUNT(Q5) > 2 | Number of selections in a multi-select |
MIN | MIN(Q5) >= 3 | Minimum numeric value in a list |
MAX | MAX(Q5) <= 10 | Maximum numeric value |
MEAN | MEAN(Q5) > 5 | Arithmetic mean |
MEDIAN | MEDIAN(Q5) == 5 | Median value |
List functions
| Function | Example | Description |
|---|---|---|
FILTER_X | FILTER_X(Q5, X > 3) | Filter list items where the expression is true |
MAP_X | MAP_X(Q5, X + 1) | Transform each list item |
OPTIONS | OPTIONS(Q3) | Access the defined options for a question (for piping) |
Arithmetic
The DSL supports arithmetic for computed variables: +, -, *, /, ** (exponent). Standard precedence applies; use parentheses to override.
Q7 + Q8 -- sum of two numeric answers
(Q7 * 100) / Q8 -- percentage calculation
Q9 ** 2 -- square
Display conditions
A display condition on a question controls whether the respondent sees it. If the condition evaluates to false (or the referenced question hasn't been answered yet), the question is skipped silently.
Set the condition field on a question:
{
"type": "text",
"text": "What did you dislike about the product?",
"condition": "Q3 IN [`4`, `5`]"
}
This question only appears if the respondent selected option 4 or 5 on Q3.
API example
curl -X PATCH https://surveys.flashpoint.ai/api/v1/surveys/{survey_id} \
-H "X-Service-Token: $TOKEN" \
-H "X-Team-ID: $TEAM_ID" \
-H "X-User-ID: $USER_ID" \
-H "Content-Type: application/json" \
-d '{
"document": {
"blocks": [{
"name": "Follow-up",
"questions": [{
"type": "text",
"text": "What did you dislike about the product?",
"condition": "Q3 IN [`4`, `5`]"
}]
}]
}
}'
Agent example
"Add a follow-up question 'What did you dislike about the product?' that only shows if Q3 is 4 or 5"
Skip rules
Skip rules are post-answer branching: after the respondent answers a question, evaluate conditions and route them accordingly. Each question can have multiple skip rules in its skips array.
Skip rule structure
{
"condition": "Q2 == `1`",
"action": {
"type": "skip",
"label": "Q7"
}
}
Action types
| Action | type | label | Behavior |
|---|---|---|---|
| Skip to question | "skip" | Required: target question label | Jump to the specified question, skipping everything in between |
| Disqualify | "disqualify" | Not used | Mark the respondent as disqualified. Survey continues to a terminate screen |
| Terminate | "terminate" | Not used | End the survey immediately |
Examples
Screen out under-18 respondents:
{
"type": "number",
"label": "Q1",
"text": "How old are you?",
"config": {"datarange": [1, 120]},
"skips": [
{
"condition": "Q1 < 18",
"action": {"type": "terminate"}
}
]
}
Skip to demographics if they selected "Not interested":
{
"skips": [
{
"condition": "Q5 == `5`",
"action": {"type": "skip", "label": "Q20"}
}
]
}
Disqualify non-owners:
{
"skips": [
{
"condition": "Q2 == `2`",
"action": {"type": "disqualify"}
}
]
}
Agent examples
- "On Q1, if the answer is less than 18, terminate the survey"
- "On Q3, if they select 'No' (option 2), skip to Q10"
- "On the screener, if they don't own the product, disqualify them"
Compound conditions
Combine multiple conditions with logical operators. Always wrap sub-expressions in parentheses for clarity.
AND — both must be true
(Q2 == `1`) AND (Q5 IN [`3`, `4`])
Show this question only to males (Q2 option 1) who are in age groups 3 or 4 (Q5).
OR — either can be true
(Q3 == `1`) OR (Q3 == `2`)
Equivalent to Q3 IN [1, 2] but useful when the two conditions reference different questions.
Complex routing
(Q2 == `1`) AND (Q4 >= 25) AND (Q4 <= 34)
Males aged 25-34 only.
((Q1 == `1`) OR (Q1 == `2`)) AND (NOT (Q6 == `5`))
Respondents who chose option 1 or 2 on Q1, but did not choose option 5 on Q6.
Grid conditions
Reference specific rows in a grid question using backslash notation:
Q3\Row1 == `5`
True if the respondent selected column 5 for Row1 in grid question Q3. The part after the backslash is the row's option label.
Variable assignments
Variable questions (type: "variable") store DSL expressions that compute values from other answers. The expression is evaluated at runtime as an assignment program (not a condition).
{
"type": "variable",
"label": "V1",
"text": "Satisfaction score",
"config": {
"definition": "Q3 + Q5 + Q7"
}
}
Variables can reference other variables, creating computed chains. The evaluator handles recursive resolution.
Common variable patterns
| Pattern | Expression | Use case |
|---|---|---|
| Sum score | Q3 + Q5 + Q7 | Composite index from multiple ratings |
| Weighted average | (Q3 * 2 + Q5 * 3) / 5 | Weighted satisfaction score |
| Selection count | COUNT(Q8) | How many items they selected in a multi-select |
| Conditional value | FILTER_X(OPTIONS(Q3), X > 3) | Filter selected options above a threshold |
Validation tools
Flashpoint.AI provides two validation tools to catch logic errors before publishing.
validate_dsl
Parses a DSL expression and checks syntax. Use before setting complex conditions.
# Agent tool call
validate_dsl(condition="(Q1 == `1`) AND (Q2 > 5)", program_type="condition")
Returns:
{
"valid": true,
"identifiers": ["Q1", "Q2"]
}
If invalid:
{
"valid": false,
"error": "Unexpected token: \"}\"",
"identifiers": []
}
Agent prompt: "Validate this condition: (Q1 == 1) AND (Q2 > 5)"
surveycheck
Runs a full validation pass on the entire survey's logic. Call this before publishing to catch:
| Check | What it catches |
|---|---|
| Unknown identifiers | A skip condition references Q99 but no question has label Q99 |
| Invalid DSLs | A condition string that fails to parse |
| Unreachable questions | A display condition that always evaluates to false |
| Post-logic identifiers | A variable definition references a label that does not exist |
The tool also offers corrections — if you reference Q99 but the closest match is Q9, it suggests the fix.
Agent prompt: "Run surveycheck on this survey to validate all the logic before we publish"
Common patterns
Screener with DQ
A typical screener flow: ask a qualifying question, disqualify those who don't qualify, then continue to the main survey.
Q1: "Do you own a car?" (select single: Yes / No)
skip: Q1 == `2` → disqualify
Q2: "What year is your car?" (year, condition: Q1 == `1`)
S1: "Thank you, you do not qualify." (terminate)
Show-if-selected
Show a follow-up only when a specific option was chosen:
Q3: "Which brands do you use?" (multi-select)
Q4: "What do you like about Nike?" (text, condition: Q3 == `1`)
Q5: "What do you like about Adidas?" (text, condition: Q3 == `2`)
Numeric range gate
Route based on a numeric threshold:
Q7: "How many employees does your company have?" (number)
skip: Q7 < 50 → skip to Q12 (small business path)
skip: Q7 >= 500 → skip to Q15 (enterprise path)
Questions Q8-Q11 are the mid-market path (50-499 employees).
Attention check
Insert a question with a known correct answer and terminate respondents who fail:
Q10: "Please select 'Strongly agree' for this question." (select single)
skip: Q10 != `1` → terminate
Next steps
- Learn about all question types: Question types
- Control sample composition: Quotas
- Validate before publishing: Lifecycle