Types

Types let you define reusable data structures for your agent. Use them in inputs, triggers, tools, resources, variables, and structured output responses.

Why Types?

  • Reusability — Define once, use in multiple places
  • Validation — Catch errors at protocol validation time
  • Documentation — Clear data contracts for your agent
  • Tool Parameters — Use complex types in tool parameters
  • Structured Output — Get typed JSON responses from the LLM

Defining Types

Types are defined in the types: section using PascalCase names:

yaml

Built-in Types

These scalar types can be used directly in inputs, resources, variables, triggers, and tool parameters:

TypeDescriptionExample Values
stringText values"hello", "user@example.com"
numberNumeric values (integers or decimals)42, 3.14, -10
integerWhole numbers only1, 100, -5
booleanTrue or falsetrue, false
unknownAny value (no type checking)Any JSON value

Note: There is no standalone array or object type. If you need typed arrays or objects, define a custom type. If you don't care about the internal structure, use unknown.

Property Fields

Each property in a type can have these fields:

FieldRequiredDescription
typeYesThe data type (built-in or custom type reference)
descriptionNoHuman-readable description
optionalNoIf true, property is not required (default: false)
enumNoList of allowed string values
constNoFixed literal value (for discriminators)

Required vs Optional

Properties are required by default. Use optional: true to make them optional:

yaml

Descriptions

Descriptions help document your types and guide LLM behavior:

yaml

Enums

Restrict string values to a specific set:

yaml

Arrays

There are two ways to define arrays:

Array Properties

Define array properties within object types using type: array and an items definition:

yaml

Top-Level Array Types

Define a named type that IS an array (not an object containing an array):

yaml

Top-level array types are useful when you need to pass arrays as tool parameters without wrapping them in an object.

Array Guidelines

When using arrays in structured output, use descriptions to guide the LLM on expected array sizes:

yaml

Note: Array length constraints (minItems, maxItems) are not enforced by LLM providers in structured output. Use descriptive prompts to guide the model.

Type References

Reference other types by their PascalCase name:

yaml

Discriminated Unions

Create types that can be one of several variants using anyOf. Each variant must have a discriminator field with a unique const value:

yaml

Union Requirements

  • Use anyOf with an array of type names (minimum 2)
  • Specify a discriminator field name
  • Each variant must have the discriminator field with a unique const value

Multiple Unions

You can have multiple discriminated unions:

yaml

Complete Example

Here's a comprehensive example combining multiple type features:

yaml

Using Types in Tools

Custom types can be used in tool parameters. Tool calls are always objects where each parameter name maps to a value.

Basic Tool Parameters

yaml

The LLM calls this with: { productId: "prod-123", includeReviews: true }

Array Parameters

For array parameters, define a top-level array type and use it as the parameter type:

yaml

The tool receives: { cartItems: [{ productId: "...", quantity: 1 }, ...] }

Why Use Named Array Types?

Named array types provide:

  • Reusability — Use the same array type in multiple tools
  • Clear schema — The array structure is validated
  • Clean tool calls — No unnecessary wrapper objects

Structured Output

Use responseType on a next-message block to get structured JSON responses instead of plain text.

Basic Example

yaml

Discriminated Unions for Response Variants

When you need different response formats based on context, use a discriminated union wrapped in an object. LLM providers don't allow anyOf (discriminated unions) at the schema root, so you must wrap them.

yaml

The client receives an object like { response: { responseType: "content_with_suggestions", content: "...", suggestions: [...] } }.

Response Type Requirements

The responseType must be an object type (regular custom type with properties).

The following cannot be used directly as responseType:

  • Discriminated unions — LLM providers don't allow anyOf at the schema root (OpenAI docs)
  • Array types — Must be wrapped in an object
  • Primitivesstring, number, etc. are not valid
yaml

How It Works

  1. The LLM generates a structured JSON response matching the type schema
  2. The response is validated against the schema
  3. The parsed object is stored in the output variable (if specified)
  4. The client SDK receives an object part instead of a text part

Client-Side Rendering

When responseType is set, the client SDK receives a UIObjectPart that can be rendered with custom UI. See the Structured Output guide for details on building custom renderers.

Best Practices

Use descriptions to guide the LLM:

yaml

Keep types focused:

Create separate types for different response formats rather than one complex type with many optional fields. Use discriminated unions when the response can be one of several distinct variants.

Handle streaming gracefully:

The client receives partial objects during streaming. Design your UI to handle incomplete data (e.g., show skeleton loaders for missing fields).

Naming Conventions

ElementConventionExamples
Type namesPascalCaseProduct, UserProfile, OrderStatus
Property namescamelCasefirstName, orderId, isActive
Enum valueslowercase_snake_case or camelCasein_stock, pending, creditCard

Validation

Types are validated when the protocol is loaded:

  • Type names must be PascalCase
  • Referenced types must exist
  • Circular references are not allowed
  • Union variants must have unique discriminator values
  • Arrays with type: array must have an items definition

Limitations

Type Definition Limits

  • No standalone array or object — Define a custom type instead, or use unknown for untyped data
  • No recursive types — A type cannot reference itself (directly or indirectly)
  • No generic types — Types are concrete, not parameterized
  • String enums onlyenum values must be strings
  • No array constraintsminItems and maxItems are not supported (LLM providers don't enforce them)

Tool Limitations

  • Tool parameters are always objects — Each tool call is { param1: value1, param2: value2, ... }
  • Array parameters need named types — Use top-level array types for array parameters

Structured Output Limitations

  • responseType must be an object type — Only object types can be used as responseType
  • Discriminated unions need object wrapper — Unions (anyOf) are not allowed at the schema root
  • Array types need object wrapper — Arrays cannot be used directly as responseType
  • Primitives are not allowedstring, number, etc. cannot be used as responseType

These limitations exist because LLM providers (OpenAI, Anthropic) require the root schema to be an object: