Beta alert
Workflows are currently in beta, join our Discord (opens in a new tab) to get the latest updates and also share any issues or feedback you might have.
Workflows are a way to chain multiple models together to create a more complex pipeline. This allows you to create a single endpoint that can take an input and pass it through multiple models in sequence. This is useful for creating more complex models that require multiple steps, or for creating a single endpoint that can handle multiple tasks.
Workflows are currently in beta, join our Discord (opens in a new tab) to get the latest updates and also share any issues or feedback you might have.
Workflow APIs work the same way as other model endpoints, you can simply send a request and get a response back. However, it is common for workflows to contain multiple steps and produce intermediate results, as each step contains their own response that could be relevant in your use-case.
Therefore, workflows benefit from the streaming feature, which allows you to get partial results as they are being generated.
The workflow API will trigger a few events during its execution, these events can be used to monitor the progress of the workflow and get intermediate results. Below are the events that you can expect from a workflow stream:
submit
eventThis events is triggered every time a new step has been submitted to execution. It contains the app_id
, request_id
and the node_id
.
{
"type": "submit",
"node_id": "stable_diffusion_xl",
"app_id": "fal-ai/fast-sdxl",
"request_id": "d778bdf4-0275-47c2-9f23-16c27041cbeb"
}
completion
eventThis event is triggered upon the completion of a specific step.
{
"type": "completion",
"node_id": "stable_diffusion_xl",
"output": {
"images": [
{
"url": "https://fal.media/result.jpeg",
"width": 1024,
"height": 1024,
"content_type": "image/jpeg"
}
],
"timings": { "inference": 2.1733 },
"seed": 6252023,
"has_nsfw_concepts": [false],
"prompt": "a cute puppy"
}
}
output
eventThe output
event means that the workflow has completed and the final result is ready.
{
"type": "output",
"output": {
"images": [
{
"url": "https://fal.media/result.jpeg",
"width": 1024,
"height": 1024,
"content_type": "image/jpeg"
}
]
}
}
error
eventThe error
event is triggered when an error occurs during the execution of a step. The error
object contains the error.status
with the HTTP status code, an error message
as well as error.body
with the underlying error serialized.
{
"type": "error",
"node_id": "stable_diffusion_xl",
"message": "Error while fetching the result of the request d778bdf4-0275-47c2-9f23-16c27041cbeb",
"error": {
"status": 422,
"body": {
"detail": [
{
"loc": ["body", "num_images"],
"msg": "ensure this value is less than or equal to 8",
"type": "value_error.number.not_le",
"ctx": { "limit_value": 8 }
}
]
}
}
}
A cool and simple example of the power of workflows is workflows/fal-ai/sdxl-sticker
, which consists of three steps:
fal-ai/fast-sdxl
.fal-ai/imageutils/rembg
.fal-ai/face-to-sticker
.What could be a tedious process of running and coordinating three different models is now a single endpoint that you can call with a single request.
import * as fal from "@fal-ai/serverless-client";
const stream = await fal.stream("workflows/fal-ai/sdxl-sticker", {
input: {
prompt: "a face of a cute puppy, in the style of pixar animation",
},
});
for await (const event of stream) {
console.log("partial", event);
}
const result = await stream.done();
console.log("final result", result);
Below are the type definition in TypeScript of events that you can expect from a workflow stream:
type WorkflowBaseEvent = {
type: "submit" | "completion" | "error" | "output";
node_id: string;
};
export type WorkflowSubmitEvent = WorkflowBaseEvent & {
type: "submit";
app_id: string;
request_id: string;
};
export type WorkflowCompletionEvent<Output = any> = WorkflowBaseEvent & {
type: "completion";
app_id: string;
output: Output;
};
export type WorkflowDoneEvent<Output = any> = WorkflowBaseEvent & {
type: "output";
output: Output;
};
export type WorkflowErrorEvent = WorkflowBaseEvent & {
type: "error";
message: string;
error: any;
};