workflow 5.0.0-beta.1 → 5.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/api-workflow.d.ts +1 -1
- package/dist/api-workflow.d.ts.map +1 -1
- package/dist/api-workflow.js +2 -2
- package/dist/api.d.ts +5 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +14 -2
- package/dist/astro.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/builtins.d.ts +17 -0
- package/dist/internal/builtins.d.ts.map +1 -1
- package/dist/internal/builtins.js +65 -1
- package/dist/internal/class-serialization.js +1 -1
- package/dist/internal/errors.js +1 -1
- package/dist/nest.js +1 -1
- package/dist/next.cjs +1 -1
- package/dist/nitro.js +1 -1
- package/dist/nuxt.js +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -2
- package/dist/stdlib.js +1 -1
- package/dist/sveltekit.js +1 -1
- package/dist/typescript-plugin.cjs +1 -1
- package/dist/vite.js +1 -1
- package/dist/workflow.js +1 -1
- package/docs/ai/index.mdx +6 -5
- package/docs/ai/resumable-streams.mdx +1 -1
- package/docs/api-reference/vitest/index.mdx +28 -1
- package/docs/api-reference/workflow/create-webhook.mdx +37 -18
- package/docs/api-reference/workflow/experimental-set-attributes.mdx +63 -0
- package/docs/api-reference/workflow/get-workflow-metadata.mdx +34 -0
- package/docs/api-reference/workflow/index.mdx +3 -0
- package/docs/api-reference/workflow-ai/durable-agent.mdx +0 -4
- package/docs/api-reference/workflow-ai/index.mdx +0 -5
- package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +0 -4
- package/docs/api-reference/workflow-api/start.mdx +5 -4
- package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +16 -6
- package/docs/api-reference/workflow-next/with-workflow.mdx +34 -2
- package/docs/changelog/attributes-mvp.mdx +368 -0
- package/docs/changelog/eager-processing.mdx +595 -0
- package/docs/changelog/index.mdx +2 -1
- package/docs/cookbook/advanced/child-workflows.mdx +313 -0
- package/docs/cookbook/advanced/meta.json +9 -0
- package/docs/cookbook/advanced/publishing-libraries.mdx +336 -0
- package/docs/cookbook/advanced/serializable-steps.mdx +147 -0
- package/docs/cookbook/advanced/upgrading-workflows.mdx +195 -0
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +156 -0
- package/docs/cookbook/agent-patterns/durable-agent.mdx +154 -0
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +255 -0
- package/docs/cookbook/agent-patterns/meta.json +4 -0
- package/docs/cookbook/common-patterns/batching.mdx +105 -0
- package/docs/cookbook/common-patterns/idempotency.mdx +107 -0
- package/docs/cookbook/common-patterns/meta.json +15 -0
- package/docs/cookbook/common-patterns/rate-limiting.mdx +228 -0
- package/docs/cookbook/common-patterns/saga.mdx +247 -0
- package/docs/cookbook/common-patterns/scheduling.mdx +129 -0
- package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +155 -0
- package/docs/cookbook/common-patterns/timeouts.mdx +99 -0
- package/docs/cookbook/common-patterns/webhooks.mdx +185 -0
- package/docs/cookbook/common-patterns/workflow-composition.mdx +111 -0
- package/docs/cookbook/index.mdx +38 -0
- package/docs/cookbook/integrations/ai-sdk.mdx +383 -0
- package/docs/cookbook/integrations/chat-sdk.mdx +307 -0
- package/docs/cookbook/integrations/meta.json +4 -0
- package/docs/cookbook/integrations/sandbox.mdx +520 -0
- package/docs/cookbook/meta.json +5 -0
- package/docs/deploying/building-a-world.mdx +1 -1
- package/docs/deploying/world/local-world.mdx +1 -1
- package/docs/deploying/world/postgres-world.mdx +6 -4
- package/docs/deploying/world/vercel-world.mdx +3 -1
- package/docs/errors/abort-signal-timeout-in-workflow.mdx +80 -0
- package/docs/errors/hook-conflict.mdx +56 -4
- package/docs/errors/index.mdx +3 -0
- package/docs/errors/runtime-decryption-failed.mdx +77 -0
- package/docs/errors/start-invalid-workflow-function.mdx +1 -1
- package/docs/foundations/cancellation.mdx +460 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/index.mdx +3 -3
- package/docs/foundations/meta.json +3 -2
- package/docs/foundations/serialization.mdx +78 -42
- package/docs/foundations/starting-workflows.mdx +6 -2
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/getting-started/astro.mdx +6 -0
- package/docs/getting-started/index.mdx +13 -7
- package/docs/getting-started/meta.json +3 -1
- package/docs/getting-started/nestjs.mdx +8 -0
- package/docs/getting-started/next.mdx +5 -3
- package/docs/getting-started/nitro.mdx +22 -0
- package/docs/getting-started/python.mdx +165 -0
- package/docs/getting-started/sveltekit.mdx +6 -0
- package/docs/getting-started/tanstack-start.mdx +241 -0
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +2 -2
- package/docs/how-it-works/event-sourcing.mdx +2 -2
- package/docs/how-it-works/meta.json +2 -1
- package/docs/internal/index.mdx +19 -0
- package/docs/internal/meta.json +5 -0
- package/docs/internal/serializable-abort-controller.mdx +148 -0
- package/docs/meta.json +1 -0
- package/docs/migration-guides/index.mdx +34 -0
- package/docs/migration-guides/meta.json +9 -0
- package/docs/migration-guides/migrating-from-aws-step-functions.mdx +358 -0
- package/docs/migration-guides/migrating-from-inngest.mdx +304 -0
- package/docs/migration-guides/migrating-from-temporal.mdx +313 -0
- package/docs/migration-guides/migrating-from-trigger-dev.mdx +328 -0
- package/docs/observability/attributes.mdx +66 -0
- package/docs/observability/index.mdx +9 -1
- package/docs/observability/meta.json +1 -1
- package/package.json +14 -13
- package/docs/foundations/common-patterns.mdx +0 -265
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python
|
|
3
|
+
description: Build durable workflows and AI agents in Python with the Vercel SDK.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Set up the Workflow Python SDK in your Python application.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/getting-started
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations
|
|
10
|
+
- /docs/foundations/workflows-and-steps
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<Callout type="warn">
|
|
14
|
+
The Python SDK is currently in **beta**. APIs and behavior may change. For the latest documentation and updates, see the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflow/python?language=py).
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
You can build durable workflows in Python using the [`vercel` Python SDK](https://pypi.org/project/vercel/). Your workflow code can pause, resume, and maintain state, just like the JavaScript and TypeScript Workflow SDK.
|
|
18
|
+
|
|
19
|
+
## Getting Started
|
|
20
|
+
|
|
21
|
+
Install the `vercel` package:
|
|
22
|
+
|
|
23
|
+
```bash filename="Terminal"
|
|
24
|
+
pip install vercel
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Configure `experimentalServices` in your `vercel.json`:
|
|
28
|
+
|
|
29
|
+
```json filename="vercel.json"
|
|
30
|
+
{
|
|
31
|
+
"experimentalServices": {
|
|
32
|
+
"ai_content_workflow": {
|
|
33
|
+
"type": "worker",
|
|
34
|
+
"entrypoint": "app/workflows/ai_content_workflow.py",
|
|
35
|
+
"topics": ["__wkf_*"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Workflows
|
|
42
|
+
|
|
43
|
+
A workflow is a stateful function that coordinates multi-step logic over time. Create a `Workflows` instance and use the `@wf.workflow` decorator to mark a function as durable:
|
|
44
|
+
|
|
45
|
+
```python filename="app/workflow.py" {3}
|
|
46
|
+
from vercel import workflow
|
|
47
|
+
|
|
48
|
+
wf = workflow.Workflows()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```python filename="app/workflows/ai_content_workflow.py" {3}
|
|
52
|
+
from app.workflow import wf
|
|
53
|
+
|
|
54
|
+
@wf.workflow
|
|
55
|
+
async def ai_content_workflow(*, topic: str):
|
|
56
|
+
draft = await generate_draft(topic=topic)
|
|
57
|
+
summary = await summarize_draft(draft=draft)
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
"draft": draft,
|
|
61
|
+
"summary": summary,
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Under the hood, the workflow compiles into a route that orchestrates execution. All inputs and outputs are recorded in an event log. If a deploy or crash happens, the system replays execution deterministically from where it stopped.
|
|
66
|
+
|
|
67
|
+
## Steps
|
|
68
|
+
|
|
69
|
+
A step is a stateless function that runs a unit of durable work inside a workflow. Use `@wf.step` to mark a function as a step:
|
|
70
|
+
|
|
71
|
+
```python filename="app/steps/generate_draft.py" {4,8}
|
|
72
|
+
import random
|
|
73
|
+
from app.workflow import wf
|
|
74
|
+
|
|
75
|
+
@wf.step
|
|
76
|
+
async def generate_draft(*, topic: str):
|
|
77
|
+
return await ai_generate(prompt=f"Write a blog post about {topic}")
|
|
78
|
+
|
|
79
|
+
@wf.step
|
|
80
|
+
async def summarize_draft(*, draft: str):
|
|
81
|
+
summary = await ai_summarize(text=draft)
|
|
82
|
+
|
|
83
|
+
# Simulate a transient error. The step automatically retries.
|
|
84
|
+
if random.random() < 0.3:
|
|
85
|
+
raise Exception("Transient AI provider error")
|
|
86
|
+
|
|
87
|
+
return summary
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Each step compiles into an isolated route. While the step executes, the workflow suspends without consuming resources. When the step completes, the workflow resumes automatically where it left off.
|
|
91
|
+
|
|
92
|
+
## Sleep
|
|
93
|
+
|
|
94
|
+
Sleep pauses a workflow for a specified duration without consuming compute resources:
|
|
95
|
+
|
|
96
|
+
```python filename="app/workflows/ai_refine.py" {7}
|
|
97
|
+
from vercel import workflow
|
|
98
|
+
|
|
99
|
+
@wf.workflow
|
|
100
|
+
async def ai_refine_workflow(*, draft_id: str):
|
|
101
|
+
draft = await fetch_draft(draft_id)
|
|
102
|
+
|
|
103
|
+
await workflow.sleep("7 days") # Wait 7 days to gather more signals.
|
|
104
|
+
|
|
105
|
+
refined = await refine_draft(draft)
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"draft_id": draft_id,
|
|
109
|
+
"refined": refined,
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The sleep call pauses the workflow and consumes no resources. The workflow resumes automatically when the time expires.
|
|
114
|
+
|
|
115
|
+
## Hooks
|
|
116
|
+
|
|
117
|
+
A hook lets a workflow wait for external events such as user actions, webhooks, or third-party API responses.
|
|
118
|
+
|
|
119
|
+
Define a hook model with Pydantic and `workflow.BaseHook`:
|
|
120
|
+
|
|
121
|
+
```python filename="app/workflows/approval.py" {3,14}
|
|
122
|
+
from vercel import workflow
|
|
123
|
+
|
|
124
|
+
class Approval(BaseModel, workflow.BaseHook):
|
|
125
|
+
"""Human approval for AI-generated drafts"""
|
|
126
|
+
|
|
127
|
+
decision: Literal["approved", "changes"]
|
|
128
|
+
notes: str | None = None
|
|
129
|
+
|
|
130
|
+
@wf.workflow
|
|
131
|
+
async def ai_approval_workflow(*, topic: str):
|
|
132
|
+
draft = await generate_draft(topic=topic)
|
|
133
|
+
|
|
134
|
+
# Wait for human approval events
|
|
135
|
+
async for event in Approval.wait(token="draft-123"):
|
|
136
|
+
if event.decision == "approved":
|
|
137
|
+
await publish_draft(draft)
|
|
138
|
+
break
|
|
139
|
+
|
|
140
|
+
revised = await refine_draft(draft, event.notes)
|
|
141
|
+
await publish_draft(revised)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Resume the workflow when data arrives:
|
|
145
|
+
|
|
146
|
+
```python filename="app/api/resume.py" {5}
|
|
147
|
+
@app.post("/api/resume")
|
|
148
|
+
async def resume(approval: Approval):
|
|
149
|
+
"""Resume the workflow when an approval is received"""
|
|
150
|
+
|
|
151
|
+
await approval.resume("draft-123")
|
|
152
|
+
return {"ok": True}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
When a hook receives data, the workflow resumes automatically. You don't need polling, message queues, or manual state management.
|
|
156
|
+
|
|
157
|
+
## Learn More
|
|
158
|
+
|
|
159
|
+
For comprehensive documentation, examples, and the latest updates, visit the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflow/python).
|
|
160
|
+
|
|
161
|
+
## Next Steps
|
|
162
|
+
|
|
163
|
+
- Learn more about the [Foundations](/docs/foundations).
|
|
164
|
+
- Check [Errors](/docs/errors) if you encounter issues.
|
|
165
|
+
- Explore the [API Reference](/docs/api-reference).
|
|
@@ -46,6 +46,12 @@ export default defineConfig({
|
|
|
46
46
|
});
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
`workflowPlugin()` accepts an options object:
|
|
50
|
+
|
|
51
|
+
| Option | Type | Default | Description |
|
|
52
|
+
| --- | --- | --- | --- |
|
|
53
|
+
| `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Set to `false` for smaller function bundles (useful for staying under the Vercel 250MB function size limit) at the cost of stack traces pointing at generated code. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. |
|
|
54
|
+
|
|
49
55
|
<Accordion type="single" collapsible>
|
|
50
56
|
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
|
|
51
57
|
<AccordionTrigger className="text-sm">
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TanStack Start
|
|
3
|
+
description: Set up your first durable workflow in a TanStack Start application.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Set up Workflow SDK in a TanStack Start app.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/getting-started
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/workflows-and-steps
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
This guide will walk through setting up your first workflow in a TanStack Start app. Along the way, you'll learn more about the concepts that are fundamental to using the Workflow SDK in your own projects.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<Steps>
|
|
17
|
+
|
|
18
|
+
<Step>
|
|
19
|
+
## Create Your TanStack Start Project
|
|
20
|
+
|
|
21
|
+
Start by creating a new TanStack Start project:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @tanstack/cli create my-workflow-app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Enter the newly made directory:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd my-workflow-app
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Install `workflow`
|
|
34
|
+
|
|
35
|
+
```package-install
|
|
36
|
+
npm i workflow
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Configure TanStack Start
|
|
40
|
+
|
|
41
|
+
TanStack Start runs on Vite, so the Workflow SDK is wired in via the same `workflow/vite` plugin. Add `workflow()` to the existing `plugins` array in your Vite config — list it first so the `"use workflow"` and `"use step"` transforms run before any other plugin processes the file.
|
|
42
|
+
|
|
43
|
+
```typescript title="vite.config.ts" lineNumbers
|
|
44
|
+
import { defineConfig } from "vite";
|
|
45
|
+
import { workflow } from "workflow/vite";
|
|
46
|
+
// ...
|
|
47
|
+
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
plugins: [
|
|
50
|
+
workflow(), // [!code highlight]
|
|
51
|
+
// ...the existing tanstackStart(), nitro(), and any other plugins
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<Accordion type="single" collapsible>
|
|
57
|
+
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
|
|
58
|
+
<AccordionTrigger className="text-sm">
|
|
59
|
+
### Setup IntelliSense for TypeScript (Optional)
|
|
60
|
+
</AccordionTrigger>
|
|
61
|
+
<AccordionContent className="[&_p]:my-2">
|
|
62
|
+
|
|
63
|
+
To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
|
|
64
|
+
|
|
65
|
+
```json title="tsconfig.json" lineNumbers
|
|
66
|
+
{
|
|
67
|
+
"compilerOptions": {
|
|
68
|
+
// ... rest of your TypeScript config
|
|
69
|
+
"plugins": [
|
|
70
|
+
{
|
|
71
|
+
"name": "workflow" // [!code highlight]
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
</AccordionContent>
|
|
79
|
+
</AccordionItem>
|
|
80
|
+
</Accordion>
|
|
81
|
+
|
|
82
|
+
</Step>
|
|
83
|
+
|
|
84
|
+
<Step>
|
|
85
|
+
|
|
86
|
+
## Create Your First Workflow
|
|
87
|
+
|
|
88
|
+
Create a new file for our first workflow:
|
|
89
|
+
|
|
90
|
+
```typescript title="src/workflows/user-signup.ts" lineNumbers
|
|
91
|
+
import { sleep } from "workflow";
|
|
92
|
+
|
|
93
|
+
export async function handleUserSignup(email: string) {
|
|
94
|
+
"use workflow"; // [!code highlight]
|
|
95
|
+
|
|
96
|
+
const user = await createUser(email);
|
|
97
|
+
await sendWelcomeEmail(user);
|
|
98
|
+
|
|
99
|
+
await sleep("5s"); // Pause for 5s - doesn't consume any resources
|
|
100
|
+
await sendOnboardingEmail(user);
|
|
101
|
+
|
|
102
|
+
return { userId: user.id, status: "onboarded" };
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
We'll fill in those functions next, but let's take a look at this code:
|
|
107
|
+
|
|
108
|
+
* We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**.
|
|
109
|
+
* The Workflow SDK's `sleep` function allows us to suspend execution of the workflow without using up any resources. A sleep can be a few seconds, hours, days, or even months long.
|
|
110
|
+
|
|
111
|
+
## Create Your Workflow Steps
|
|
112
|
+
|
|
113
|
+
Let's now define those missing functions.
|
|
114
|
+
|
|
115
|
+
```typescript title="src/workflows/user-signup.ts" lineNumbers
|
|
116
|
+
import { FatalError } from "workflow"
|
|
117
|
+
|
|
118
|
+
// Our workflow function defined earlier
|
|
119
|
+
|
|
120
|
+
async function createUser(email: string) {
|
|
121
|
+
"use step"; // [!code highlight]
|
|
122
|
+
|
|
123
|
+
console.log(`Creating user with email: ${email}`);
|
|
124
|
+
|
|
125
|
+
// Full Node.js access - database calls, APIs, etc.
|
|
126
|
+
return { id: crypto.randomUUID(), email };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function sendWelcomeEmail(user: { id: string; email: string; }) {
|
|
130
|
+
"use step"; // [!code highlight]
|
|
131
|
+
|
|
132
|
+
console.log(`Sending welcome email to user: ${user.id}`);
|
|
133
|
+
|
|
134
|
+
if (Math.random() < 0.3) {
|
|
135
|
+
// By default, steps will be retried for unhandled errors
|
|
136
|
+
throw new Error("Retryable!");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function sendOnboardingEmail(user: { id: string; email: string}) {
|
|
141
|
+
"use step"; // [!code highlight]
|
|
142
|
+
|
|
143
|
+
if (!user.email.includes("@")) {
|
|
144
|
+
// To skip retrying, throw a FatalError instead
|
|
145
|
+
throw new FatalError("Invalid Email");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log(`Sending onboarding email to user: ${user.id}`);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Taking a look at this code:
|
|
153
|
+
|
|
154
|
+
* Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
|
|
155
|
+
* If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
|
|
156
|
+
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
157
|
+
|
|
158
|
+
<Callout>
|
|
159
|
+
We'll dive deeper into workflows, steps, and other ways to suspend or handle events in [Foundations](/docs/foundations).
|
|
160
|
+
</Callout>
|
|
161
|
+
|
|
162
|
+
</Step>
|
|
163
|
+
|
|
164
|
+
<Step>
|
|
165
|
+
|
|
166
|
+
## Create Your Route Handler
|
|
167
|
+
|
|
168
|
+
To invoke your new workflow, add a server handler at `src/routes/api/signup.ts`:
|
|
169
|
+
|
|
170
|
+
```typescript title="src/routes/api/signup.ts"
|
|
171
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
172
|
+
import { json } from "@tanstack/react-start";
|
|
173
|
+
import { start } from "workflow/api";
|
|
174
|
+
import { handleUserSignup } from "../../workflows/user-signup";
|
|
175
|
+
|
|
176
|
+
export const Route = createFileRoute("/api/signup")({
|
|
177
|
+
server: {
|
|
178
|
+
handlers: {
|
|
179
|
+
POST: async ({ request }) => {
|
|
180
|
+
const { email } = await request.json();
|
|
181
|
+
// Executes asynchronously and doesn't block your app
|
|
182
|
+
await start(handleUserSignup, [email]);
|
|
183
|
+
return json({ message: "User signup workflow started" });
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow.
|
|
191
|
+
|
|
192
|
+
<Callout>
|
|
193
|
+
Workflows can be triggered from API routes or any server-side code.
|
|
194
|
+
</Callout>
|
|
195
|
+
|
|
196
|
+
</Step>
|
|
197
|
+
|
|
198
|
+
</Steps>
|
|
199
|
+
|
|
200
|
+
## Run in development
|
|
201
|
+
|
|
202
|
+
To start your development server, run the following command in your terminal in the TanStack Start root directory:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm run dev
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Once your development server is running, you can trigger your workflow by running this command in the terminal:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Check the dev server logs to see your workflow execute as well as the steps that are being processed.
|
|
215
|
+
|
|
216
|
+
Additionally, you can use the [Workflow SDK CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Open the observability Web UI on http://localhost:3456
|
|
220
|
+
npx workflow web
|
|
221
|
+
# or if you prefer a terminal interface, use the CLI inspect command
|
|
222
|
+
npx workflow inspect runs
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+

|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Deploying to production
|
|
230
|
+
|
|
231
|
+
Workflow SDK apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration.
|
|
232
|
+
|
|
233
|
+
<FluidComputeCallout />
|
|
234
|
+
|
|
235
|
+
Check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere.
|
|
236
|
+
|
|
237
|
+
## Next Steps
|
|
238
|
+
|
|
239
|
+
* Learn more about the [Foundations](/docs/foundations).
|
|
240
|
+
* Check [Errors](/docs/errors) if you encounter issues.
|
|
241
|
+
* Explore the [API Reference](/docs/api-reference).
|