Call Workflows from Pages
You can bind and trigger Workflows from Pages Functions by deploying a Workers project with your Workflow definition and then invoking that Worker using service bindings or a standard fetch()
call.
Service Bindings allow you to call a Worker from another Worker or a Pages Function without needing to expose it directly.
To do this, you will need to:
- Deploy your Workflow in a Worker
- Create a Service Binding to that Worker in your Pages project
- Call the Worker remotely using the binding
For example, if you have a Worker called workflows-starter
, you would create a new Service Binding in your Pages project as follows, ensuring that the service
name matches the name of the Worker your Workflow is defined in:
{ "services": [ { "binding": "WORKFLOW_SERVICE", "service": "workflows-starter" } ]}
services = [ { binding = "WORKFLOW_SERVICE", service = "workflows-starter" }]
Your Worker can expose a specific method (or methods) that only other Workers or Pages Functions can call over the Service Binding.
In the following example, we expose a specific createInstance
method that accepts our Payload
and returns the InstanceStatus
from the Workflows API:
import { WorkerEntrypoint } from "cloudflare:workers";
export default class WorkflowsService extends WorkerEntrypoint { // Currently, entrypoints without a named handler are not supported async fetch() { return new Response(null, { status: 404 }); }
async createInstance(payload) { let instance = await this.env.MY_WORKFLOW.create({ params: payload, });
return Response.json({ id: instance.id, details: await instance.status(), }); }}
import { WorkerEntrypoint } from "cloudflare:workers";
interface Env { MY_WORKFLOW: Workflow;}
type Payload = { hello: string;}
export default class WorkflowsService extends WorkerEntrypoint<Env> { // Currently, entrypoints without a named handler are not supported async fetch() { return new Response(null, {status: 404}); }
async createInstance(payload: Payload) { let instance = await this.env.MY_WORKFLOW.create({ params: payload });
return Response.json({ id: instance.id, details: await instance.status(), }); }}
Your Pages Function would resemble the following:
export const onRequest = async (context) => { // This payload could be anything from within your app or from your frontend let payload = { hello: "world" }; return context.env.WORKFLOWS_SERVICE.createInstance(payload);};
interface Env { WORKFLOW_SERVICE: Service;}
export const onRequest: PagesFunction<Env> = async (context) => { // This payload could be anything from within your app or from your frontend let payload = {"hello": "world"} return context.env.WORKFLOWS_SERVICE.createInstance(payload)};
To learn more about binding to resources from Pages Functions, including how to bind via the Cloudflare dashboard, refer to the bindings documentation for Pages Functions.
An alternative to setting up a Service Binding is to call the Worker over HTTP by using the Workflows Workers API to create
a new Workflow instance for each incoming HTTP call to the Worker:
// This is in the same file as your Workflow definitionexport default { async fetch(req, env) { let instance = await env.MY_WORKFLOW.create({ params: payload, }); return Response.json({ id: instance.id, details: await instance.status(), }); },};
// This is in the same file as your Workflow definitionexport default { async fetch(req: Request, env: Env): Promise<Response> { let instance = await env.MY_WORKFLOW.create({ params: payload }); return Response.json({ id: instance.id, details: await instance.status(), }); },};
Your Pages Function can then make a regular fetch
call to the Worker:
export const onRequest = async (context) => { // Other code let payload = { hello: "world" }; const instanceStatus = await fetch("https://YOUR_WORKER.workers.dev/", { method: "POST", body: JSON.stringify(payload), // Send a payload for our Worker to pass to the Workflow });
return Response.json(instanceStatus);};
export const onRequest: PagesFunction<Env> = async (context) => { // Other code let payload = {"hello": "world"} const instanceStatus = await fetch("https://YOUR_WORKER.workers.dev/", { method: "POST", body: JSON.stringify(payload) // Send a payload for our Worker to pass to the Workflow })
return Response.json(instanceStatus);};
You can also choose to authenticate these requests by passing a shared secret in a header and validating that in your Worker.
- Learn more about how to programatically call and trigger Workflows from the Workers API
- Understand how to send events and parameters when triggering a Workflow
- Review the Rules of Workflows and best practices for writing Workflows