Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ products:
date: 2025-08-22
---

import { Render, PackageManagers, TypeScriptExample } from "~/components"
import { Render, PackageManagers, TypeScriptExample } from "~/components";

You can now build [Workflows](/workflows/) using Python. With Python Workflows, you get automatic retries, state persistence, and the ability to run multi-step operations that can span minutes, hours, or weeks using Python’s familiar syntax and the [Python Workers](/workers/languages/python/) runtime.
You can now build [Workflows](/workflows/) using Python. With Python Workflows, you get automatic retries, state persistence, and the ability to run multi-step operations that can span minutes, hours, or weeks using Python’s familiar syntax and the [Python Workers](/workers/languages/python/) runtime.

Python Workflows use the same step-based execution model as JavaScript Workflows, but with Python syntax and access to Python’s ecosystem. Python Workflows also enable [DAG (Directed Acyclic Graph) workflows](/workflows/python/dag/), where you can define complex dependencies between steps using the depends parameter.

Expand All @@ -36,9 +36,10 @@ class PythonWorkflowStarter(WorkflowEntrypoint):

await my_second_step()

async def on_fetch(request, env):
await env.MY_WORKFLOW.create()
return Response("Hello Workflow creation!")
class Default(WorkerEntrypoint):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to import WorkerEntrypoint as well

async def fetch(self, request):
await self.env.MY_WORKFLOW.create()
return Response("Hello Workflow creation!")
```

:::note
Expand All @@ -47,4 +48,4 @@ Python Workflows requires a `compatibility_date = "2025-08-01"`, or lower, in yo

Python Workflows support the same core capabilities as JavaScript Workflows, including sleep scheduling, event-driven workflows, and built-in error handling with configurable retry policies.

To learn more and get started, refer to [Python Workflows documentation](/workflows/python/).
To learn more and get started, refer to [Python Workflows documentation](/workflows/python/).
15 changes: 9 additions & 6 deletions src/content/docs/workflows/python/bindings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@ Create (trigger) a new instance of a given Workflow.
type.

```python
from pyodide.ffi import to_js
from js import Object
from pyodide.ffi import to_js
from workers import WorkerEntrypoint, Response


async def on_fetch(request, env, ctx):
event = {"foo": "bar"}
options = to_js({"params": event}, dict_converter=Object.fromEntries)
await env.MY_WORKFLOW.create(options)
return Response.json({"status": "success"})
class Default(WorkerEntrypoint):
async def fetch(self, request):
event = {"foo": "bar"}
options = to_js({"params": event}, dict_converter=Object.fromEntries)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this is correct at the moment. But since we recently started wrapping the binding in the workers module, we can do this internally (with a compat flag)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it would be good to do that, we plan to do this for all bindings eventually

await self.env.MY_WORKFLOW.create(options)
return Response.json({"status": "success"})
```

:::note
Expand Down
10 changes: 5 additions & 5 deletions src/content/docs/workflows/python/python-workers-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,13 @@ class DemoWorkflowClass(WorkflowEntrypoint):

### Create an instance via binding

Note that `env` is a Javascript object exposed to the Python script via [JsProxy](https://pyodide.org/en/stable/usage/api/python-api/ffi.html#pyodide.ffi.JsProxy). You can
access the binding like you would on a Javascript worker. Refer to the [Workflow binding documentation](/workflows/build/workers-api/#workflow) to learn more about the methods available.
Note that `env` is a JavaScript object exposed to the Python script via [JsProxy](https://pyodide.org/en/stable/usage/api/python-api/ffi.html#pyodide.ffi.JsProxy). You can access the binding like you would on a JavaScript worker. Refer to the [Workflow binding documentation](/workflows/build/workers-api/#workflow) to learn more about the methods available.

Let's consider the previous binding called `MY_WORKFLOW`. Here's how you would create a new instance:

```python
async def on_fetch(request, env):
instance = await env.MY_WORKFLOW.create()
return Response.json({"status": "success"})
class Default(WorkerEntrypoint):
async def fetch(self, request):
instance = await self.env.MY_WORKFLOW.create()
return Response.json({"status": "success"})
```