> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maia.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeSafe Decide



\<table><tbody><tr><td>Project Availability</td>
            \<td /></tr>
          \<tr><td>Component Type</td>
            \<td>Orchestration</td></tr>
          \<tr><td>Connection Inputs</td>
            \<td>One</td></tr>
          \<tr><td>Connection Outputs</td>
            \<td>Unlimited</td></tr></tbody></table>

The TypeSafe Decide component asks [TypeSafe](https://docs.typesafe.ai/introduction/quickstart)'s Jev model typed questions about each row of a Snowflake table, and writes the answers to a table. Each [question](https://docs.typesafe.ai/primitives) is a Choice (one of a set of options), a Score (a position on an ordered scale), or a Noul (the probability that a statement about the row is true).Each answer is written to typed columns, such as the chosen label, a score, or a probability, and Choice and Score answers also get a confidence value. You can join the results back to the input table by the key column.### Use caseThis component lets you classify, rate, and flag rows of data in your orchestration pipeline. For example, you can use it to:* Classify customer reviews or support tickets into a fixed set of categories, with a Choice question.
* Rate reviews or survey answers on a scale that you describe—for example, satisfaction from "very dissatisfied" to "very satisfied"—with a Score question.
* Flag rows where a statement holds—for example, "the customer asks for a refund"—with a Noul question, which gives a probability that you can apply a threshold to later in your pipeline.
* Ask several of these questions about the same rows in one component.> [!NOTE]
>
> The component sends one request to TypeSafe for each source row whose key isn't NULL. TypeSafe charges per input token. Read [Models](https://docs.typesafe.ai/models) for pricing and rate limits.***## PrerequisitesBefore you use this component, you need:- A TypeSafe account and API key. To get an API key from the TypeSafe console, read TypeSafe's [Quick start](https://docs.typesafe.ai/introduction/quickstart).
- A TypeSafe connection that holds the API key. Create it on the project's **Connections** tab, as described in [Add a connection](https://docs.maia.ai/docs/guides/connections.md#add-a-connection). Select **TypeSafe** as the provider and `API Key` as the **Authentication type**, and enter your key in **API Key**. You can also create the connection from the component's **Connection** property.The Maia runner reads the key column and the input columns from the source table, and sends each row's input column values to TypeSafe's API using the API key of the selected connection. Snowflake doesn't call TypeSafe.***## Properties**Name** `string` *required*A human-readable name for the component.### Connect**Connection** `drop-down` *required*Select a TypeSafe [connection](https://docs.maia.ai/docs/guides/connections.md). This connection holds the TypeSafe API key that the component uses. Only TypeSafe connections are listed.If the required connection doesn't yet exist, you can create it here by selecting **Add Connection** in the drop-down. Read [Add a connection](https://docs.maia.ai/docs/guides/connections.md#add-a-connection) for further details, following that process from step 4 onwards. A connection created here is visible in the **Connections** tab and available for other components to use.**Model** `drop-down` *required*Specify the Jev [model](https://docs.typesafe.ai/models) that answers the questions. The default is `jev-latest`, TypeSafe's alias for its newest stable release. The alias moves to each new release, so answers can change without any change to your pipeline. To keep the same model across runs, select a versioned model. Select `[Custom]` if you wish to specify a model not available in the drop-down list.**Custom model name** `string` *required*The ID of your custom model. Only required if you selected `[Custom]` in **Model**. Use the full model ID, as listed in TypeSafe's [Models](https://docs.typesafe.ai/models).### Source**Database** `drop-down` *required*The Snowflake *source* database. The special value `[Environment Default]` uses the database defined in the environment. Read [Databases, Tables and Views - Overview](https://docs.snowflake.com/en/guides-overview-db) to learn more.**Schema** `drop-down` *required*The Snowflake *source* schema. The special value `[Environment Default]` uses the schema defined in the environment. Read [Database, Schema, and Share DDL](https://docs.snowflake.com/en/sql-reference/ddl-database.html) to learn more.**Table** `drop-down` *required*An existing Snowflake table or view to use as the input.**Key column** `drop-down` *required*Select the column that identifies each row. The component copies this column, with its source data type, to the destination table, so you can join the answers back to the input table. Rows whose key is NULL are skipped: they aren't sent to TypeSafe or written to the destination table.**Input columns** `column editor` *required*Select the source columns that TypeSafe sees for each row. The component sends each row's values to TypeSafe as one JSON object, the row's [state](https://docs.typesafe.ai/concepts/state), with one key for each input column.- **Column:** A column from the input table.
- **Name in state:** Optional. The key that TypeSafe sees for the column—for example, a more descriptive name. If you leave it blank, the key is the column name. Each input column needs a different key.Values of `VARIANT`, `OBJECT`, and `ARRAY` columns are sent as nested JSON rather than as text. The key column isn't sent to TypeSafe unless you also select it here.Toggle **Text mode** on at the bottom of the dialog to open a multi-line editor that lets you add items in a single block. For more information, read [Text mode](https://docs.maia.ai/docs/guides/components-overview.md#text-mode).To use grid variables, toggle **Use Grid Variable** on. For more information, read [Grid variables](https://docs.maia.ai/docs/guides/grid-variables.md).**Limit** `integer`Set a limit for the number of rows to read from the table. The default is 1000. Leave it blank to read every row\.Rows are read from the table in no particular order, so when you set a limit, which rows are read can differ from run to run.### Configure**Questions** `column editor` *required*The questions to ask about each row, one row per question.- **Name:** A name for the question. The question's output columns are named after it, as described in [Explanation of output](#explanation-of-output), and keep its case exactly as you enter it. Each name must be unique, and names that differ only in case count as the same name. No two output columns can have the same name—for example, you can't name a question `MODEL_NAME`, or use a Choice question named `A` alongside a question named `A_CONFIDENCE`.
- **Type:** The kind of answer: [Choice](https://docs.typesafe.ai/primitives/choice), [Score](https://docs.typesafe.ai/primitives/score), or [Noul](https://docs.typesafe.ai/primitives/noul).
- **Instructions format:** **Text** or **JSON**. The default is **Text**. Select **JSON** to give structured instructions, as described in [Advanced: structure](https://docs.typesafe.ai/primitives/advanced). The **Instructions** cell must then hold valid JSON.
- **Instructions:** The question itself.Toggle **Text mode** on at the bottom of the dialog to open a multi-line editor that lets you add items in a single block. For more information, read [Text mode](https://docs.maia.ai/docs/guides/components-overview.md#text-mode).To use grid variables, toggle **Use Grid Variable** on. For more information, read [Grid variables](https://docs.maia.ai/docs/guides/grid-variables.md).**Criteria** `column editor`The options, levels, or yes/no definitions for each question, one row per criterion.- **Question:** The name of the question that the criterion belongs to.
- **Label:** The criterion's label. Labels must be unique within a question.
- **Description format:** **Text** or **JSON**. The default is **Text**. Select **JSON** to give a structured description. The **Description** cell must then hold valid JSON.
- **Description:** Optional. What the criterion means.The criteria a question needs depend on the **Type** selected for it in **Questions**:- **Choice:** At least one and no more than 255 criteria. Each label is an option, and the answer is one of the labels.
- **Score:** At least two and no more than 10 criteria. These are the levels of the scale, listed from lowest to highest. The first level is level 0.
- **Noul:** Optional. Up to two criteria, labeled `true` and `false`, that describe what a yes and a no mean.Toggle **Text mode** on at the bottom of the dialog to open a multi-line editor that lets you add items in a single block. For more information, read [Text mode](https://docs.maia.ai/docs/guides/components-overview.md#text-mode).To use grid variables, toggle **Use Grid Variable** on. For more information, read [Grid variables](https://docs.maia.ai/docs/guides/grid-variables.md).### Destination**Database** `drop-down` *required*The target Snowflake database. The special value `[Environment Default]` uses the database defined in the environment. Read [Databases, Tables and Views - Overview](https://docs.snowflake.com/en/guides-overview-db) to learn more.**Schema** `drop-down` *required*The target Snowflake schema. The special value `[Environment Default]` uses the schema defined in the environment. Read [Database, Schema, and Share DDL](https://docs.snowflake.com/en/sql-reference/ddl-database.html) to learn more.**Table** `string` *required*The Snowflake table to write the answers to. What happens if the table already exists depends on **Create table options**.**Create table options** `drop-down` *required*- **Replace if Table Exists:** The pipeline will run despite the table already existing. The table will be recreated.
- **Fail if Table Exists:** If the table already exists, the pipeline will fail to run. This is the default setting.
- **Append:** If the table already exists, any new rows (records) will be added to the table without modifying or deleting existing rows. If the table does *not* exist, it is created and any new rows are inserted.To append to an existing table, the table must already have every column that the component writes, with names that match exactly, including case. Other columns in the table, and the order of the columns, don't matter. If a column is missing, the run fails before any row is sent to TypeSafe. Each run adds all of its rows, even for keys that are already in the table.**Snowflake only:**This component uses the **CREATE OR REPLACE** clause. When using the **REPLACE** clause, it also applies the **COPY GRANTS** clause. When you clone or create a new object (such as a table, view, schema, or database) from an existing one, the new object doesn't automatically inherit the original's grants (privileges). However, with the **COPY GRANTS** clause, you can seamlessly transfer object-level privileges from the source object to the new one. This helps maintain consistent access control and simplifies permission management when cloning or recreating objects. For more information, read [Snowflake COPY GRANTS](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-copy-grants).### Advanced Settings**Concurrency** `integer`The maximum number of concurrent requests to TypeSafe, from 1 to 16. The default is four. Higher values increase throughput, up to your TypeSafe organization's [rate limits](https://docs.typesafe.ai/models#rate-limits). Rate-limited requests are retried.## Explanation of outputThe destination table contains the key column, then each question's columns in question order, then four fixed columns. Each column's Snowflake data type is shown in parentheses.| Output column | Question type | Description |
| - | - | - |
| Key column (its source name and data type) | All | The row's key value. |
| `<name>` (`VARCHAR`) | Choice | The label of the option with the highest probability. |
| `<name>` (`FLOAT`) | Score | The score: a probability-weighted position on the levels, from 0 (the first level) to the number of the last level. The score can fall between two levels. |
| `<name>` (`FLOAT`) | Noul | The probability, from 0 to 1, that the statement is true. |
| `<name>_CONFIDENCE` (`FLOAT`) | Choice, Score | TypeSafe's [confidence](https://docs.typesafe.ai/confidence) in the answer, from 0 to 1. |
| `<name>_PROBABILITIES` (`VARIANT`) | Choice, Score | The probability of each option or level, as a JSON object. For a Choice question, the keys are the option labels. For a Score question, the keys are the level numbers (`"0"`, `"1"`, and so on), not the labels. |
| `MODEL_NAME` (`VARCHAR`) | All | The versioned ID of the model that answered, even when **Model** is `jev-latest`. |
| `INPUT_TOKENS` (`NUMBER`) | All | The number of input tokens that TypeSafe counted for the row. |
| `PROVIDER_REQUEST_ID` (`VARCHAR`) | All | TypeSafe's ID for the request, also set on a failed row when TypeSafe returned one. Useful when you contact TypeSafe support. |
| `ERROR_METADATA` (`VARCHAR`) | All | NULL for an answered row. For a failed row, the reason that it failed. |`<name>` is the question's **Name**. Noul questions have no `_CONFIDENCE` or `_PROBABILITIES` columns, because the probability is the whole answer. Output column names keep the case that you entered in **Name**, so in later SQL, enclose a name that contains lowercase letters in double quotes.If the request for a row is longer than the model's [context length](https://docs.typesafe.ai/models#context-length), only that row fails. The row is still written, with NULL in its answer columns, `MODEL_NAME`, and `INPUT_TOKENS`, and the reason in `ERROR_METADATA`. The rest of the run carries on.Temporary TypeSafe errors—rate limiting, overload, server errors, timeouts, and connection errors—are retried, up to five attempts for each row. Any other failure stops the run, such as a rejected API key, a request that TypeSafe refuses, retries running out, or an error writing to the destination table. When TypeSafe returned a request ID, the error message includes it.> [!WARNING]
>
> When a run stops, the rows already written stay in the destination table, and later rows aren't written. The component creates or replaces the table before it reads the first row, and writes rows in batches of up to 500 as answers arrive. With **Replace if Table Exists**, a run that stops early leaves a table that contains only some of the rows.The component checks its properties before it sends any row to TypeSafe. A mistake such as a question name used twice, the wrong number of criteria for a question type, or invalid JSON in a JSON cell fails the run, or the sample, before any request is made.When a run finishes, the task message gives the number of rows read, answered, failed, and skipped because their key is NULL, the number of input tokens used, and the number of retried requests, if any.The **Sample** tab sends up to 10 rows to TypeSafe and shows the answers as they would be written to the destination table. Sampling uses the connection's API key, and TypeSafe charges for it as it does for a run.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.