Skip to content

Commit dbae6bd

Browse files
committed
workflows: events API
1 parent eef3a0c commit dbae6bd

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
title: New `waitForEvent` API landed in Workflows
3+
description: Use the new `waitForEvent` API in Workflows to wait for approvals, additional data and/or webhooks from external systems.
4+
products:
5+
- workflows
6+
date: 2025-02-18T14:00:00Z
7+
---
8+
9+
import { Render, TypeScriptExample } from "~/components";
10+
11+
[Workflows](/workflows/) now allows your workflows to wait for events through the [`waitForEvent`](/workflows/build/events-and-parameters/) API, enabling human-in-loop, approval-driven and/or webhook-reactive workflows and AI agents that can act on external events as they execute.
12+
13+
Calling `step.waitForEvent` is similar to calling any other step in your Workflow: give the step a name, set an optional timeout, and return the event as state:
14+
15+
<TypeScriptExample filename="workflow.ts">
16+
```ts
17+
// Within your Workflow definition
18+
let event = await step.waitForEvent("unique event name", { timeout: "1 day" })
19+
```
20+
</TypeScriptExample>
21+
22+
You can then pass an event to a specific Workflow instance by calling `sendEvent`:
23+
24+
<TypeScriptExample filename="index.ts">
25+
```ts
26+
// Within a Worker, Queue handler, or Durable Object
27+
await env.WORKFLOW.get(instanceId).sendEvent("unique event name", eventPayload)
28+
```
29+
</TypeScriptExample>
30+
31+
For example, you can build Workflows that can wait for third party webhooks by using `await step.waitForEvent` inside the Workflow and `sendEvent` from the [Workers API](/workflows/build/workers-api/#workflowinstance):
32+
33+
<TypeScriptExample filename="index.ts">
34+
```ts
35+
type InboundBillingEvent = {
36+
name: string;
37+
timestamp: Date;
38+
invoiceId: string;
39+
amount: number;
40+
description: string;
41+
}
42+
43+
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
44+
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
45+
let state = step.do("my first step", async () => {
46+
// Code here
47+
})
48+
49+
// Pass an optional type
50+
let invoiceEventData = await step.waitForEvent<InboundBillingEvent>("wait for paid invoice", { timeout: "7 days" })
51+
52+
let res = await step.do("process invoice", await async () => {
53+
// Process the invoiceEventData
54+
// If the payload doesn't work, we can trigger another step.waitForEvent from here too!
55+
}
56+
57+
// Continue on with the workflow
58+
}
59+
}
60+
61+
export default {
62+
async fetch(req: Request, env: Env, ctx: ExecutionContext) {
63+
let path = new URL(req.url).pathname
64+
switch (path) {
65+
case "/runInstance":
66+
if (req.method === "POST") {
67+
let params = new URL(req.url).searchParams
68+
let invoiceId = params.get("invoiceId")
69+
let instance = await env.WORKFLOW.create({ id: invoiceId })
70+
71+
return Response.json({ instance_id: instance.id })
72+
case "/handleWebhook":
73+
if (req.method === "POST") {
74+
let instanceId = req.headers.get("x-workflow-invoice-id")
75+
let jsonPayload = await req.json()
76+
await env.WORKFLOW.get(instanceId).sendEvent("process invoice", jsonPayload)
77+
return Response.json({ success: true })
78+
default:
79+
return Response.json({ error: "Not found" }, { status: 404 })
80+
}
81+
}
82+
}
83+
```
84+
</TypeScriptExample>
85+
86+
Visit the Workflows [documentation on events and parameters](/workflows/build/events-and-parameters/) to learn more about the new event API.

src/content/changelogs/workflows.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ productLink: "/workflows/"
55
productArea: Developer platform
66
productAreaLink: /workers/platform/changelog/platform/
77
entries:
8+
- publish_date: "2024-02-18"
9+
title: "New `waitForEvent` API"
10+
description: |-
11+
You can now send events to a running Workflow using the new [`waitForEvent`](/workflows/build/events-and-parameters/) API.
12+
13+
This allows you to prompt for human-in-the-loop interactions, such as requiring approvals via email, text or API; requesting more data from an upstream system; and/or incoming webhooks, such as those from a payment provider or billing system.
814
- publish_date: "2024-12-19"
915
title: "Better instance control, improved queued logic, and step limit increased"
1016
description: |-

src/content/docs/workflows/build/events-and-parameters.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ npx wrangler@latest workflows trigger workflows-starter '{"some":"data"}'
6060
🚀 Workflow instance "57c7913b-8e1d-4a78-a0dd-dce5a0b7aa30" has been queued successfully
6161
```
6262

63+
## Wait for events
64+
65+
TODO
66+
6367
## TypeScript and type parameters
6468

6569
By default, the `WorkflowEvent` passed to the `run` method of your Workflow definition has a type that conforms to the following, with `payload` (your data), `timestamp`, and `instanceId` properties:

0 commit comments

Comments
 (0)