Overview
Pydantic v2 is used for input and output validation. The params and secure_params run() arguments and its return type should inherit from Pydantic BaseModel. You can use any type, constraint, or validator Pydantic supports.
Input validation errors are raised before your run() function executes; output validation errors are raised after it returns. Pydantic validation errors, like any exceptions raised by run(), are reported as run failures.
Don’t catch WorkflowError at the top level of your run() function unless you plan to return a valid Result. Swallowing errors silently can lead to missing or incorrect results.
Example
class Result(BaseModel):
customer_id: str = Field(min_length=8, max_length=16)
name: str
# This will raise a validation error if customer_id is too short
return Result(customer_id="ABC", name="Jane")
If your Result validation fails, the run reports a failure. Make sure your output constraints match what your workflow actually produces.
Field Constraints
Use Pydantic’s Field() constraints liberally on Params and SecureParams — they catch bad input before your workflow starts, saving time and compute.
Use Field() to add validation rules:
from pydantic import BaseModel, Field
class Params(BaseModel):
name: str = Field(min_length=1, max_length=100)
post_number: int = Field(gt=0)
customer_id: str = Field(min_length=8, max_length=16)
| Constraint | Type | Description |
|---|
min_length / max_length | str | String length bounds |
ge / le | int, float | Greater/less than or equal |
gt / lt | int, float | Strictly greater/less than |
default | any | Default value if not provided |
Special Types
Pydantic’s built-in types work out of the box:
from pydantic import BaseModel, Field, EmailStr, AnyUrl
class Params(BaseModel):
email: EmailStr
website: AnyUrl
name: str = Field(min_length=1, max_length=100)
Optional Fields
Use | None with a default for optional fields:
class Result(BaseModel):
user_id: str
phone: str | None = Field(default=None)
email: EmailStr | None = Field(default=None)
Default Values
class Params(BaseModel):
url: str = Field(default="https://example.com", min_length=1)
max_retries: int = Field(default=3, ge=1, le=10)
List Fields
class Params(BaseModel):
selected_customers: list[str]
tags: list[str] = Field(default_factory=list)
Add constraints to catch bad input early. A min_length=1 on a required string prevents empty strings from reaching your workflow logic.