Step 1: Install the packages
bun add workflow @workflow/aibun add workflow @workflow/aiStep 2: Update Next.js config
Update the Next.js configuration:
// next.config.ts
import type { NextConfig } from "next";
import { withWorkflow } from "workflow/next";
const nextConfig: NextConfig = {
/* config options here */
reactCompiler: true,
};
export default withWorkflow(nextConfig);// next.config.ts
import type { NextConfig } from "next";
import { withWorkflow } from "workflow/next";
const nextConfig: NextConfig = {
/* config options here */
reactCompiler: true,
};
export default withWorkflow(nextConfig);Logging in Workflows
Workflow functions run in a restricted environment that doesn't support Node.js modules like fs, events, or worker_threads. Since pino uses these modules, you cannot import the logger directly in workflow functions.
Instead, wrap logger calls in a step function:
import { logger } from "@/lib/common/logger";
type LogLevel = "info" | "warn" | "error" | "debug";
/**
* Workflow-safe logger step.
* Wraps pino logger calls in a step function to avoid bundling
* Node.js modules (fs, events, worker_threads) into workflow functions.
*/
export async function log(
level: LogLevel,
message: string,
data?: Record<string, unknown>,
): Promise<void> {
"use step";
if (data) {
logger[level](data, message);
} else {
logger[level](message);
}
}import { logger } from "@/lib/common/logger";
type LogLevel = "info" | "warn" | "error" | "debug";
/**
* Workflow-safe logger step.
* Wraps pino logger calls in a step function to avoid bundling
* Node.js modules (fs, events, worker_threads) into workflow functions.
*/
export async function log(
level: LogLevel,
message: string,
data?: Record<string, unknown>,
): Promise<void> {
"use step";
if (data) {
logger[level](data, message);
} else {
logger[level](message);
}
}Then use the step in your workflow:
import { log } from "./steps/logger";
export async function chatWorkflow({ chatId, userMessage }) {
"use workflow";
// Use the step wrapper instead of importing logger directly
await log("info", "Router decision", { next, reasoning });
}import { log } from "./steps/logger";
export async function chatWorkflow({ chatId, userMessage }) {
"use workflow";
// Use the step wrapper instead of importing logger directly
await log("info", "Router decision", { next, reasoning });
}This pattern applies to any library that uses Node.js modules. Move the import and usage into a step function to isolate it from the workflow runtime.