Schemas
Blueprint that defines the structure, format, and validation rules for data.
A schema is a blueprint that defines the structure, required fields, data types, and validation rules for a piece of data. In Botpress, schemas are primarily used to ensure that data passed between various components—such as actions, modules, or API requests—meets the expected format and constraints.
Schemas are useful for:
- Data Validation: Preventing errors by ensuring that data adheres to the expected format.
- Consistency: Enforcing a consistent structure for data across different components.
- Error Reduction: Reducing the likelihood of runtime errors caused by unexpected or malformed data.
- Ease of Maintenance: Making it easier to understand and manage data flow within your Botpress application.
Creating and Using Schemas
JSON Schema Basics
Botpress uses JSON Schema, a standard for describing the structure and validation constraints of JSON documents.
A JSON Schema can define:
- Types: The type of data (e.g., string, number, object, array).
- Required Fields: Fields that must be present in the data.
- Enum Values: Specific allowed values for a field.
- Nested Structures: Complex data structures with multiple levels.
Creating a schema
You can create a new schema by navigating to the Schema menu in the left-hand menu. You can also create a new schema when adding a new variable through the Variables menu.
Using schemas
You can use schemas instead of selecting a variable type like String or Number. This means that the variable will contain the information in the structure you've defined in your schema.
For example, you might use a variable to contain information about your end user. This variable can use a schema to contain information like email, age, name, and home address, all contained in a single variable and structured by your schema.
Testing Schemas
Here's a simple demo schema you can create to familiarize yourself with them.
- Create a schema for a user object with the following properties:
zui.object({
name: zui.string(),
age: zui.number(),
email: zui.string().email(),
address: zui.object({
street: zui.string(),
city: zui.string(),
zip: zui.string().length(5)
})
})
- Create a Variable of the user schema type and name it
UserInformation
. - [optionally] you can use these variables as inputs for workflows, allowing the user to fill in the schema as though it were a form.
Usage in AI Task
- Task Instructions:
Fetch name, age, email and address from the provided input
- AI Task Input:
Rohan Kokkula, 26, at [email protected], received a mysterious parcel at his doorstep:
42 Emerald Lane, Mystic Falls, 560078.
Inside, a map beckoned him to a hidden world beneath Mumbai's bustling streets,
where history and magic intertwined.
- Store result in variables: Select the Variable we created above.
Conditionally Show Inputs - Input trees
We'll show you how to use discriminated unions in Zod to conditionally include fields in an object schema. We'll go through two examples:
- Changing the type of a variable based on user input.
- Conditionally showing an extra setting when an "Advanced Setting" toggle is activated.
Example 1: Changing the Type of a Variable
In this example, we'll create a schema that allows a variable (value
) to be either a string or a number, depending on the user's choice.
z.object({
inputData: z.discriminatedUnion('inputType', [
z.object({
inputType: z.literal('Text'),
// When inputType is 'Text', value is a string
value: z.string().title('Text Value').placeholder('Enter text')
}),
z.object({
inputType: z.literal('Number'),
// When inputType is 'Number', value is a number
value: z.number().title('Numeric Value').placeholder('Enter a number')
})
])
});
How It Works
inputType
: Acts as the discriminator that determines the type of thevalue
field.- Discriminated Union:
- If
inputType
is"Text"
, the schema expectsvalue
to be a string. - If
inputType
is"Number"
, the schema expectsvalue
to be a number.
- If
This approach is useful when you want to change the type of a variable based on a user's selection.
Example 2: Conditionally Showing Extra Settings
This example demonstrates how to include an extra field when an "Advanced Setting" toggle is turned on.
z.object({
// ... your other inputs
// Using discriminated union to handle the advanced setting toggle with Yes/No options
settings: z.discriminatedUnion('advancedSetting', [
z.object({
advancedSetting: z.literal('No').describe('Advanced setting is disabled'),
// No extra settings when advancedSetting is "No"
}),
z.object({
advancedSetting: z.literal('Yes').describe('Advanced setting is enabled'),
// Extra setting when advancedSetting is "Yes"
extraSetting: z.string()
.title('Extra Setting')
.placeholder('Enter extra setting')
.describe('Additional setting enabled when the advanced setting is turned on')
})
])
});
How It Works
advancedSetting
: Acts as the discriminator that determines whether to include theextraSetting
field.- Discriminated Union:
- If
advancedSetting
is"No"
, the schema does not includeextraSetting
. - If
advancedSetting
is"Yes"
, the schema requiresextraSetting
to be provided.
- If
This pattern is useful when you want to include additional settings only when an "Advanced Setting" option is enabled.
Trying it out
Trying it out is very easy!
- Open Botpress Studio
- Create and save the schema with discriminatedUnion fields
- Create a variable in a workflow other than main, set its type to the schema's saved name.
- Click on the input node for the workflow, then toggle the variable as an input.
- Go to another workflow and add a card that points to the one with the schema input.
- You'll now be able to able to see your input tree in all it's glory!
Summary
- Discriminated Unions in Zod allow you to conditionally change the shape of an object.
- They are useful for:
- Changing the type of a variable based on user input.
- Conditionally including fields based on a toggle or option.
By using discriminated unions, you can build dynamic and flexible schemas that adapt based on user selections, making your form validation and UI more intuitive and responsive.
Updated 2 months ago