Hatchet Python V1 Migration Guide
This guide will help you migrate Hatchet workflows from the V0 SDK to the V1 SDK.
Introductory Example
First, a simple example of how to define a task with the V1 SDK:
The API has changed significantly in the V1 SDK. Even in this simple example, there are some notable highlights:
- Tasks can now be declared with
hatchet.task, meaning you no longer have to create a workflow explicitly to define a task. This should feel similar to how e.g. Celery handles task definition. Note that we recommend declaring a workflow in many cases, but the simplest possible way to get set up is to usehatchet.task. - Tasks have a new signature. They now take two arguments:
inputandcontext. Theinputis either of typeinput_validator(a Pydantic model you provide to the workflow), or is anEmptyModel, which is a helper Pydantic model Hatchet provides and uses as a default. Thecontextis once again the HatchetContextobject. - Workflows can now be registered on a worker by using the
workflowskeyword argument to theworkermethod, although the oldregister_workflowsmethod is still available.
Pydantic
Hatchet’s V1 SDK makes heavy use of Pydantic models, and recommends you do too! Let’s dive into a more involved example using Pydantic in a fanout example.
In this example, we use a few more new SDK features:
- Workflows are now declared with
hatchet.workflow, and then have their corresponding tasks registered withworkflow.task. - We define two Pydantic models,
ParentInputandChildInput, and pass them to the parent and child workflows asinput_validators. Note that now, theinputparameters for the tasks in those two workflows are Pydantic models of those types, and we can treat them as such. This replaces the oldcontext.workflow_inputfor accessing the input to the workflow / task - now, we just can access the input directly. - When we want to spawn the child workflow, we can use the
runmethods on thechild_workflowobject, which is a HatchetWorkflow, instead of needing to refer to the workflow by its name (a string). Theinputfield torun()is now also properly typed asChildInput. - The child workflow (see below) makes use of some of Hatchet’s DAG features, such as defining parent tasks. In the new SDK,
parentsof a task are defined as a list ofTaskobjects as opposed to as a list of strings, so now,process2hasprocess(theTask) as its parent, as opposed to"process"(the string). This also allows us to usectx.task_output(process)to access the output of theprocesstask in theprocess2task, and know the type of that output at type checking time.
See our Pydantic documentation for more.
Other Breaking Changes
There have been a number of other breaking changes throughout the SDK in V1.
Typing improvements:
- All times and durations, such as
timeoutandschedule_timeoutfields are nowdatetime.timedeltaobjects instead of strings (e.g."10s"becomestimedelta(seconds=10)). - External-facing protobuf objects, such as
StickyStrategyandConcurrencyLimitStrategy, have been replaced by native Python enums to make working with them easier. - All interactions with the
TaskandWorkflowobjects are now typed, so you know e.g. what the type of the input to the task needs to be at type checking time (we see this in the Pydantic example above). - All external-facing types that are used for triggering tasks, scheduling tasks, etc. are now Pydantic objects, as opposed to being
TypedDicts. - The return type of each
Taskis restricted to aJSONSerializableMappingor a Pydantic model, to better align with what the Hatchet Engine expects. - The
ClientConfignow uses Pydantic Settings, and we’ve removed the static methods on the Client forfrom_environmentandfrom_configin favor of passing configuration in correctly. - The REST API wrappers, which previously were under
hatchet.rest, have been completely overhauled.
Naming changes:
- We no longer have nested
aioclients for async methods. Instead, async methods throughout the entire SDK are prefixed byaio_, similar to Langchain’s use of theaprefix to indicate async. For example, to run a task, you may now either useworkflow.run()orworkflow.aio_run(). - All functions on Hatchet clients are now verbs. For instance the way to list workflow runs is via
hatchet.runs.list(). max_runson the worker has been renamed toslots.
Removals:
sync_to_asynchas been removed. We recommend reading our asyncio documentation for our recommendations on handling blocking work in otherwise async tasks.
Other miscellaneous changes:
- As shown in the Pydantic example above, there is no longer a
spawn_workflow(s)method on theContext.runis now the preferred method for spawning workflows, which will automatically propagate the parent’s metadata to the child workflow.
Other New features
There are a handful of other new features that will make interfacing with the SDK easier, which are listed below.
- Concurrency keys using the
inputto a task are now checked for validity at runtime. If the task’sinput_validatordoes not contain a field that’s used in a key, Hatchet will reject the task when it’s created. For example, if the key isinput.user_id, theinput_validatorPydantic model must contain auser_idfield. - There is now an
on_success_taskon theWorkflowobject, which works just like an on-failure task, but it runs after all upstream tasks have succeeded.