VariableDefinition extends the same SchemaFieldDefinition base that structured output fields use — that’s why a type string written for a schema field and a type string written for a variable follow identical rules, are parsed by the same type parser, and are coerced by the same logic. This page is the single reference for that notation.
Type strings are parsed with Python’s
ast module (no eval), then handed to Pydantic for runtime validation. Only the forms documented below are recognized — anything else raises a parse error.Scalars
type
Text data.
type
Integer numbers.
type
Decimal numbers.
type
Boolean values (
true/false).type
Accepts any value, no validation. Both
Any and any are accepted spellings.Enum types are not supported. Use
str with a clear description, and steer allowed values through the system prompt.Collections
type
A list of items of type
T, e.g. list[str], list[int].type
A mapping from keys of type
K to values of type V, e.g. dict[str, int].list and dict (with no type arguments) are also valid.
Collections nest to arbitrary depth — the parser recurses through subscripts, so dict[str, list[int]], list[dict[str, float]], and deeper combinations all parse correctly:
Nullability
type
Optional/nullable value of type
T. None | T (reversed order) works identically.type
Equivalent alternate spelling for
T | None.Union directly: Union[T, None] parses to the same nullable type as T | None and Optional[T].
General, non-nullable unions are also accepted (e.g. str | int), though in practice nullable forms (T | None) are by far the most common use.
Coercion rules
Coercion only applies to variables — specifically when a value is assigned to a variable viavariable_assignments, a runtime input, or a checkpoint-restored value. Structured output fields are produced by the model directly and validated by BAML; they are not run through this coercion step.
Nullability interaction: variables vs. structured output
This is the one interaction worth understanding before you rely onnull values flowing between agents.
1
A null field does not overwrite a non-nullable variable
When a This exists because a
variable_assignments entry reads a structured output field that the model set to null, and the variable’s declared type is not nullable (no None/Optional[...] in its type), the assignment is skipped entirely — the variable keeps whatever value it already had. The system logs:None value assigned into a non-nullable variable would otherwise be rejected the next time variables are assembled (e.g. on the following execution, once it’s been through a checkpoint), failing the whole session.2
The structured output layer tolerates null on any field, regardless of notation
Internally, every structured output field is marked optional at the BAML schema-building layer, even if you declared it as a plain non-nullable type like
str. This is deliberate: without it, a model returning null for a field typed str would hard-fail the generation call (Expected string, got null) for the entire agent turn. So declaring a structured output field as T | None is not required merely to keep BAML from rejecting the model’s null — the runtime already tolerates that for every field.3
Declare both sides nullable anyway, if null is meaningful
To actually store and use a null result, declare the variable’s type nullable (
float | None, not float) — that’s what determines whether the assignment in Step 1 is skipped or allowed through. Declaring the structured output field as T | None too keeps the schema’s intent explicit and matches the variable it feeds, even though the BAML layer would tolerate null either way.Common errors
Cannot parse type string '...'
Cannot parse type string '...'
The type string isn’t valid Python expression syntax at all. Exact message:
Unknown type '...'
Unknown type '...'
The base name isn’t one of the recognized keywords (
str, int, float, bool, list, dict, any/Any, Optional, Union). This is the error you’ll hit for things like List[str], enum[...], or a typo. Exact message:Invalid type '...'
Invalid type '...'
The string parsed into a type, but Pydantic couldn’t build a validator for it. Exact message:
Invalid type '{type_str}': {error}.Variable has invalid BAML type
Variable has invalid BAML type
Raised at config-validation time for a variable whose
type doesn’t parse. Exact message:The hint text in this message is misleading —
str[]/int[] are not valid notation. Use list[str]/list[int] instead.'{field}' expected {type}, got {type}
'{field}' expected {type}, got {type}
Raised when a variable’s current value doesn’t match its declared type after coercion (for example, a non-nullable variable ended up holding
None, or a static assignment can’t be coerced into the declared type).Used by
Structured Output
Define typed fields the agent must extract.
Variables
Define typed values threaded through prompts and assignments.