AI wrangles answer questions about each row of data. Use them to choose between options, score against ordered criteria, or evaluate how likely a statement is to be true.
Each wrangle accepts one or more named questions. All questions for the same row are evaluated together in one request. The input columns remain in the result, and answers are written to columns named from each question.
These wrangles use Typesafe. Supply a Typesafe API key with
api_key: ${TYPESAFE_API_KEY}using a recipe variable or managed secret. For local execution, theTYPESAFE_API_KEYenvironment variable is also supported.
Output names are configured inside each question, rather than at the wrangle level. Omitting a question's output creates columns named from its label; it does not automatically overwrite the input.
The examples below show illustrative results. Actual answers, probabilities, and confidence values may vary. Probabilities and confidence values use a scale of 0–1.
For extracting attributes into a custom schema, see Extract AI.
Use ai.choose to select the best-fitting option for each question. Each answer includes the selected option, confidence, and the probability of every option.
Define the available options under criteria. Option labels become the possible choices and the keys in the probability dictionary.
wrangles:
- ai.choose:
input: Product Description
api_key: ${TYPESAFE_API_KEY}
questions:
Category:
instructions: Which category best describes this product?
criteria:
Bearing: Supports rotating shafts or reduces rotational friction.
Seal: Prevents fluid leakage or contamination.
Other: Does not fit either category.
| → |
|
Add multiple questions under questions to evaluate them together for each row.
Set output inside a question to rename its columns. For Choose, provide exactly three names in this order: selected option, confidence, probabilities.
wrangles:
- ai.choose:
input: Product Description
api_key: ${TYPESAFE_API_KEY}
questions:
Category:
instructions: Which category best describes this product?
criteria:
Bearing: Supports rotating shafts.
Seal: Prevents leakage.
Other: Any other product.
output:
- Product Category
- Category Confidence
- Category Probabilities
Material:
instructions: Which material is explicitly stated?
criteria:
Steel: Steel is explicitly stated.
Rubber: Rubber is explicitly stated.
Unknown: No material is explicitly stated.
The first question creates Product Category, Category Confidence, and Category Probabilities. The second creates Material, Material_confidence, and Material_probabilities.
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| input | str, int, list | Column name, zero-based column position, or list of columns to evaluate. Omit to use all columns. | |
| questions | ✓ | dict | Nonempty mapping of question labels to question definitions. See Question Parameters below. |
| api_key | str | Typesafe API key. Required unless available through the local TYPESAFE_API_KEY environment variable. | |
| model | str | Override the configured Typesafe model. | |
| provider | str | Provider adapter. Currently only typesafe is supported. | |
| protocol | str | Provider protocol. Currently only systemone is supported. | |
| threads | int | Maximum concurrent row requests. Packaged default: 10. | |
| timeout | int, float | Positive timeout in seconds per HTTP attempt. Packaged default: 30. | |
| retries | int | Additional attempts after transient failures. Packaged default: 1. Set to 0 to disable retries. | |
| cache | bool | Enable local result caching. Packaged default: false. | |
| cache_ttl | int, float | Positive cache lifetime in seconds. Packaged default: 3600. Applies when caching is enabled. | |
| where | str | SQL-style condition selecting rows to process. | |
| where_params | list, dict | Positional or named parameters for where, using SQLite placeholders such as ? or :name. | |
| if | str | Condition determining whether the entire wrangle runs. |
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| instructions | ✓ | str, dict, list | Nonempty instructions describing the decision. Supports row-value templates. |
| criteria | ✓ | dict | Between 1 and 255 nonblank option labels mapped to descriptions. Descriptions may be nonempty strings, objects, arrays, or null. |
| type | str | Optional. If supplied, must be choose. | |
| output | list | Exactly three column names: choice, confidence, probabilities. Omit or leave blank to use the question label and its suffixes. With for_each, use one output name instead. | |
| for_each | dict | Repeat the question over a list or dictionary column. See Repeating Questions below. |
Use ai.score to evaluate each row against ordered criteria. Criteria define positions from 0 to N−1, where N is the number of criteria.
The score is the probability-weighted position and can fall between criteria. Each answer includes the score, confidence, and probabilities keyed by the criterion descriptions.
A score is not a probability or percentage. Four criteria produce scores from 0 to 3. There is no scale parameter or automatic rescaling.
Order the criteria from the lowest to the highest level.
wrangles:
- ai.score:
input: Message
api_key: ${TYPESAFE_API_KEY}
questions:
Severity:
instructions: How much does this issue prevent users from completing their work?
criteria:
- Appearance issue; work is unaffected.
- A feature fails; another method remains available.
- Work cannot continue using any available method.
| → |
|
In this example, the weighted score is 0 × 0.0 + 1 × 0.6 + 2 × 0.4 = 1.4.
Provide exactly three output names in this order: score, confidence, probabilities.
wrangles:
- ai.score:
input: Product Description
api_key: ${TYPESAFE_API_KEY}
questions:
Completeness:
instructions: How complete is the product description?
criteria:
- No useful product information.
- Product type only.
- Product type and some specifications.
- Product type and detailed specifications.
output:
- Description Score
- Description Confidence
- Description Probabilities
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| input | str, int, list | Column name, zero-based column position, or list of columns to evaluate. Omit to use all columns. | |
| questions | ✓ | dict | Nonempty mapping of question labels to question definitions. See Question Parameters below. |
| api_key | str | Typesafe API key. Required unless available through the local TYPESAFE_API_KEY environment variable. | |
| model | str | Override the configured Typesafe model. | |
| provider | str | Provider adapter. Currently only typesafe is supported. | |
| protocol | str | Provider protocol. Currently only systemone is supported. | |
| threads | int | Maximum concurrent row requests. Packaged default: 10. | |
| timeout | int, float | Positive timeout in seconds per HTTP attempt. Packaged default: 30. | |
| retries | int | Additional attempts after transient failures. Packaged default: 1. Set to 0 to disable retries. | |
| cache | bool | Enable local result caching. Packaged default: false. | |
| cache_ttl | int, float | Positive cache lifetime in seconds. Packaged default: 3600. Applies when caching is enabled. | |
| where | str | SQL-style condition selecting rows to process. | |
| where_params | list, dict | Positional or named parameters for where, using SQLite placeholders such as ? or :name. | |
| if | str | Condition determining whether the entire wrangle runs. |
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| instructions | ✓ | str, dict, list | Nonempty instructions describing what to score. Supports row-value templates. |
| criteria | ✓ | list | Between 2 and 10 unique, nonblank strings in ascending scoring order. Positions run from 0 to N−1. Descriptions also become the probability dictionary keys. |
| type | str | Optional. If supplied, must be score. | |
| output | list | Exactly three column names: score, confidence, probabilities. Omit or leave blank to use the question label and its suffixes. With for_each, use one output name instead. | |
| for_each | dict | Repeat the question over a list or dictionary column. See Repeating Questions below. |
Use ai.true_false to evaluate how likely a statement is to be true.
Each question creates two columns: the probability that the statement is true and the supplied true criterion. If no true criterion is supplied, the criterion column contains an empty string.
True False returns a probability from 0 to 1. It does not return a Boolean, a confidence column, or a generated explanation.
Criteria are optional when the instructions fully describe the question.
wrangles:
- ai.true_false:
input: Message
api_key: ${TYPESAFE_API_KEY}
questions:
Human Escalation:
instructions: Is the customer asking to speak with a human agent?
| → |
|
Provide "true" and/or "false" criteria to describe the outcomes.
Set exactly two output names in this order: probability, true criterion.
wrangles:
- ai.true_false:
input: Message
api_key: ${TYPESAFE_API_KEY}
questions:
Repeat Contact:
instructions: Has the customer contacted support about this before?
criteria:
"true": Mentions an earlier attempt to contact support.
"false": Gives no indication of an earlier contact.
output:
- Repeat Contact Probability
- Repeat Contact Criterion
For the message above, an illustrative result is:
| Repeat Contact Probability | Repeat Contact Criterion |
|---|---|
| 0.94 | Mentions an earlier attempt to contact support. |
Quote the
"true"and"false"keys in YAML so they remain strings rather than Boolean values.
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| input | str, int, list | Column name, zero-based column position, or list of columns to evaluate. Omit to use all columns. | |
| questions | ✓ | dict | Nonempty mapping of question labels to question definitions. See Question Parameters below. |
| api_key | str | Typesafe API key. Required unless available through the local TYPESAFE_API_KEY environment variable. | |
| model | str | Override the configured Typesafe model. | |
| provider | str | Provider adapter. Currently only typesafe is supported. | |
| protocol | str | Provider protocol. Currently only systemone is supported. | |
| threads | int | Maximum concurrent row requests. Packaged default: 10. | |
| timeout | int, float | Positive timeout in seconds per HTTP attempt. Packaged default: 30. | |
| retries | int | Additional attempts after transient failures. Packaged default: 1. Set to 0 to disable retries. | |
| cache | bool | Enable local result caching. Packaged default: false. | |
| cache_ttl | int, float | Positive cache lifetime in seconds. Packaged default: 3600. Applies when caching is enabled. | |
| where | str | SQL-style condition selecting rows to process. | |
| where_params | list, dict | Positional or named parameters for where, using SQLite placeholders such as ? or :name. | |
| if | str | Condition determining whether the entire wrangle runs. |
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| instructions | ✓ | str, dict, list | Nonempty instructions describing the statement to evaluate. Supports row-value templates. |
| criteria | dict | Optional descriptions under the quoted string keys "true" and/or "false". Descriptions may be nonempty strings, objects, or arrays. | |
| type | str | Optional. If supplied, must be true_false. | |
| output | list | Exactly two column names: probability, true criterion. Omit or leave blank to use the question label and its suffix. With for_each, use one output name instead. | |
| for_each | dict | Repeat the question over a list or dictionary column. See Repeating Questions below. |
Use ai.answers to combine Choose, Score, and True False questions in the same wrangle.
Every question declares its own type. Questions can share the same type or use different types, and each retains its type's output fields.
This example classifies a support message, scores its severity, and checks whether it describes repeat contact.
wrangles:
- ai.answers:
input:
- Message
- Browser
api_key: ${TYPESAFE_API_KEY}
questions:
Issue Type:
type: choose
instructions: Which kind of issue is being reported?
criteria:
Bug: A feature behaves incorrectly or fails.
Account: Sign-in, access, or account administration.
Other: A request outside those categories.
Severity:
type: score
instructions: How much does this issue prevent users from completing their work?
criteria:
- Appearance issue; work is unaffected.
- A feature fails; another method remains available.
- Work cannot continue using any available method.
Repeat Contact:
type: true_false
instructions: Has the customer contacted support about this before?
criteria:
"true": Mentions an earlier attempt to contact support.
Example input:
| Message | Browser |
|---|---|
| Export crashes here but works in Chrome. I have reported this twice already. | Safari |
Illustrative output is shown as YAML so the probability dictionaries are readable. Input columns remain in the result.
- Message: Export crashes here but works in Chrome. I have reported this twice already.
Browser: Safari
Issue Type: Bug
Issue Type_confidence: 1.0
Issue Type_probabilities:
Bug: 1.0
Account: 0.0
Other: 0.0
Severity: 1.4
Severity_confidence: 0.4
Severity_probabilities:
Appearance issue; work is unaffected.: 0.0
A feature fails; another method remains available.: 0.6
Work cannot continue using any available method.: 0.4
Repeat Contact: 0.97
Repeat Contact_true_criteria: Mentions an earlier attempt to contact support.
Each question can include its own output setting. Choose and Score questions require three output names; True False questions require two.
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| input | str, int, list | Column name, zero-based column position, or list of columns to evaluate. Omit to use all columns. | |
| questions | ✓ | dict | Nonempty mapping of question labels to question definitions. Every question must declare a type. |
| api_key | str | Typesafe API key. Required unless available through the local TYPESAFE_API_KEY environment variable. | |
| model | str | Override the configured Typesafe model. | |
| provider | str | Provider adapter. Currently only typesafe is supported. | |
| protocol | str | Provider protocol. Currently only systemone is supported. | |
| threads | int | Maximum concurrent row requests. Packaged default: 10. | |
| timeout | int, float | Positive timeout in seconds per HTTP attempt. Packaged default: 30. | |
| retries | int | Additional attempts after transient failures. Packaged default: 1. Set to 0 to disable retries. | |
| cache | bool | Enable local result caching. Packaged default: false. | |
| cache_ttl | int, float | Positive cache lifetime in seconds. Packaged default: 3600. Applies when caching is enabled. | |
| where | str | SQL-style condition selecting rows to process. | |
| where_params | list, dict | Positional or named parameters for where, using SQLite placeholders such as ? or :name. | |
| if | str | Condition determining whether the entire wrangle runs. |
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| type | ✓ | str | choose, score, or true_false. Required even when all questions use the same type. |
| instructions | ✓ | str, dict, list | Nonempty instructions describing the question. Supports row-value templates. |
| criteria | Depends on type | dict, list | Required option mapping for choose; required ordered list for score; optional true/false mapping for true_false. |
| output | list | Three names for choose or score; two for true_false. Omit or leave blank to derive names from the question label. With for_each, use one output name instead. | |
| for_each | dict | Repeat the question over a list or dictionary column. See Repeating Questions below. |
All four AI wrangles support inserting row values into question instructions and criterion descriptions using {{ column_name }} placeholders.
Templates can reference any column in the row, even when input selects only some columns. Referenced values become part of the questions sent to the provider.
Given these input columns:
| Description | Proposed Category | Manufacturer Name |
|---|---|---|
| CONTAINER 24X15X11 CHARCOAL | Containers | Example Supply |
Use column values in the question:
wrangles:
- ai.score:
input: Description
api_key: ${TYPESAFE_API_KEY}
questions:
Category Fit:
instructions: >-
How strongly does this description support "{{ Proposed_Category }}"?
The manufacturer is "{{ Manufacturer_Name }}".
Distinguish missing information from contradictory information.
criteria:
- Contradicted
- Weakly supported
- Supported but incomplete
- Clearly supported
This creates Category Fit, Category Fit_confidence, and Category Fit_probabilities.
| Rule | Details |
|---|---|
| Column aliases | Replace each character outside A–Z, a–z, 0–9, and underscore with an underscore. Manufacturer Name becomes Manufacturer_Name. |
| Starting character | The alias must start with a letter or underscore. |
| Case | Column aliases are case-sensitive. |
| Supported locations | Instructions and criterion description string values, including values inside nested objects and arrays. |
| Literal names | Question labels, option labels, dictionary keys, and output names are not templated. |
| String values | Inserted as text. |
| Other values | Finite JSON-compatible values are inserted as JSON text. |
| Missing references | Raise an error before provider calls. |
| Ambiguous references | Raise an error if multiple columns produce the same referenced alias. |
| Expressions | Python expressions, attribute access, and Jinja filters are not supported. |
| Substitution | Runs once. Braces inside an inserted value remain literal text. |
For example, Product Name and Product-Name both produce the alias Product_Name. Rename one of those columns before referencing that alias.
For Score questions, rendered criterion descriptions must remain nonblank and unique because they also become probability dictionary keys.
{{ column_name }}inserts values from the current row.${variable}uses recipe variables, such as API keys or reusable settings.
Add for_each to a question to evaluate each candidate in a list or dictionary cell.
Each row can contain a different collection of candidates. The expanded questions are evaluated together with any ordinary questions in the same wrangle.
Repeated questions produce one output column containing a collection of answers.
The Candidate Categories cell contains a dictionary with stable keys:
- Description: CONTAINER 24X15X11 CHARCOAL
Manufacturer Name: Example Supply
Candidate Categories:
category_1: Containers
category_2: Shelves
category_3: ""
Use for_each.values to name that column and for_each.variable to name the placeholder for each candidate:
wrangles:
- ai.score:
input: Description
api_key: ${TYPESAFE_API_KEY}
questions:
Category Fits:
for_each:
values: Candidate Categories
variable: category
instructions: >-
How strongly does this description support "{{ category }}"?
The manufacturer is "{{ Manufacturer_Name }}".
Distinguish missing information from contradictory information.
criteria:
- Contradicted
- Weakly supported
- Supported but incomplete
- Clearly supported
Illustrative contents of the Category Fits output cell:
category_1:
value: Containers
score: 2.77
confidence: 0.77
probabilities:
Contradicted: 0.01
Weakly supported: 0.03
Supported but incomplete: 0.14
Clearly supported: 0.82
category_2:
value: Shelves
score: 0.23
confidence: 0.77
probabilities:
Contradicted: 0.82
Weakly supported: 0.14
Supported but incomplete: 0.03
Clearly supported: 0.01
category_3: {}
The dictionary keys are preserved. Each evaluated answer includes its original candidate as value.
The blank string in category_3 reserves a slot without sending a question to the provider.
A list-valued source cell is also supported:
Candidate Categories:
- Containers
- Shelves
- ""
The same recipe returns a list of answers in the original order. The last item is {} because the corresponding candidate is a blank string.
Unlike ordinary questions, repeated questions accept one output name:
questions:
category_fit:
for_each:
values: Candidate Categories
variable: category
instructions: How strongly does the description support "{{ category }}"?
criteria:
- Contradicted
- Weakly supported
- Supported but incomplete
- Clearly supported
output: Category Fits
A one-item list such as output: [Category Fits] is also accepted.
Use split.dictionary to expose each candidate's answer as a separate column:
wrangles:
- ai.score:
input: Description
api_key: ${TYPESAFE_API_KEY}
questions:
Category Fits:
for_each:
values: Candidate Categories
variable: category
instructions: How strongly does the description support "{{ category }}"?
criteria:
- Contradicted
- Weakly supported
- Supported but incomplete
- Clearly supported
- split.dictionary:
input: Category Fits
- split.dictionary:
input: category_1
output:
- "*": category_1_*
The first split creates columns such as category_1, category_2, and category_3.
The second exposes fields such as category_1_value, category_1_score, category_1_confidence, and category_1_probabilities.
| Parameter | Required | Data Type | Notes |
|---|---|---|---|
| for_each.values | ✓ | str | Exact source column name, including spaces and punctuation. Each cell must contain a list or a dictionary with string keys. |
| for_each.variable | ✓ | str | Local placeholder name for the current candidate. Use ASCII letters, digits, or underscores, starting with a letter or underscore. |
| output | str, list | One output column name, or a one-item list. Omit or leave blank to use the question label. |
The local variable takes precedence over a column alias with the same name within that question.
for_each.values must name a column. Literal candidate collections and JSON-encoded strings are not accepted in its place.
| Source value | Output behavior |
|---|---|
| Dictionary | Dictionary of answers preserving the original keys and order. |
| List | List of answers preserving the original order. |
| Empty dictionary | Returns an empty dictionary. |
| Empty list | Returns an empty list. |
| Empty or whitespace-only candidate string | Returns an empty dictionary at that position without generating a question. |
| Other JSON-compatible candidate value | Evaluated normally and retained as value in the answer. |
Missing keys or positions are not added automatically. Supply blank-string candidates when consistent placeholder slots are needed.
When all questions expand to empty collections or blank-string candidates, no provider request is made.
Repeated questions retain the fields belonging to their type:
| Question Type | Answer Fields |
|---|---|
| choose | value, choice, confidence, probabilities |
| score | value, score, confidence, probabilities |
| true_false | value, probability_true, true_criteria |
Question labels must be nonblank strings. For ordinary questions, omitted output, null output, or a blank string selects the default names:
| Question Type | Default Output Columns |
|---|---|
| choose | label, label_confidence, label_probabilities |
| score | label, label_confidence, label_probabilities |
| true_false | label, label_true_criteria |
| Any question with for_each | label |
Explicit output names must be nonblank and unique across all questions in the wrangle. Ordinary questions require the complete ordered list of names; partial lists and a single nonempty string are invalid.
The threads setting controls concurrent row requests. Each row's questions share one request rather than making a separate request for every question.
The timeout setting applies to each HTTP attempt, not the complete batch. Retries and queued rows can make total execution time longer.
Only transient failures are retried. Invalid credentials, invalid question definitions, and malformed answers fail rather than producing substitute answers.
Caching is disabled by default for these four AI wrangles. Enable it when repeated identical requests should reuse successful results:
wrangles:
- ai.choose:
input: Product Description
api_key: ${TYPESAFE_API_KEY}
cache: true
cache_ttl: 3600
questions:
Category:
instructions: Which category best describes this product?
criteria:
Bearing: Supports rotating shafts.
Seal: Prevents leakage.
Other: Any other product.
The cache is local to the running Python process. When enabled, duplicate concurrent requests can share a result.
Packaged limits are a one-hour lifetime, 512 entries, and 65,536 bytes per cached value. Request identity includes the provider, endpoint, model, credentials, input, and rendered questions.
Process-level WRANGLES_AI_CACHE_* settings can override caller and catalog cache settings. These controls are separate from the cache settings used by extract.ai.