en un clic
flow-convert-workflow-definition
// Convert Flow SDK workflow class to Output SDK workflow() function. Use when migrating workflow.ts files from class-based to functional definitions.
// Convert Flow SDK workflow class to Output SDK workflow() function. Use when migrating workflow.ts files from class-based to functional definitions.
Validate and fix folder structure for Output SDK workflows. Use to ensure migrated workflows follow the correct structure conventions.
Convert Flow SDK activities.ts to Output SDK steps.ts. Use when migrating activity functions to step definitions with typed parameters.
Convert inline prompts and prompt arrays to .prompt files with YAML frontmatter. Use when migrating prompts from Flow SDK format to Output SDK prompt files.
Create scenario files for testing migrated Output SDK workflows. Use to set up test inputs in the scenarios/ subfolder.
Fix ESLint issues in migrated Output SDK code. Use when seeing lint errors after migration, or when writing new Output SDK code that needs to follow project conventions.
Remove try-catch antipattern from step calls during Flow to Output SDK migration. Use when converting workflow code that wraps step calls in try-catch blocks.
| name | flow-convert-workflow-definition |
| description | Convert Flow SDK workflow class to Output SDK workflow() function. Use when migrating workflow.ts files from class-based to functional definitions. |
| allowed-tools | ["Bash","Read","Write","Grep","Edit"] |
This skill guides the conversion of Flow SDK workflow classes to Output SDK functional workflow definitions. Workflows orchestrate step execution and define the overall data flow.
During Migration:
workflow.ts from class-based to functional| Aspect | Flow SDK | Output SDK |
|---|---|---|
| Definition | Class with execute() method | workflow() function |
| Input/Output | TypeScript interfaces | Zod schemas |
| Activity Calls | Direct function calls | Step calls with object params |
| Error Handling | Try-catch blocks | Let errors propagate |
| Imports | @flow/sdk | @outputai/core |
// workflow.ts
import { Workflow, WorkflowScope } from '@flow/sdk';
import { fetchUser, processData, saveResults } from './activities';
interface WorkflowInput {
userId: string;
processType: string;
}
interface WorkflowOutput {
success: boolean;
resultId: string;
}
export class DataProcessingWorkflow implements Workflow<WorkflowInput, WorkflowOutput> {
async execute( input: WorkflowInput ): Promise<WorkflowOutput> {
try {
// Get user data
const user = await fetchUser( input.userId );
// Process the data
const processed = await processData( user, input.processType );
// Save results
const result = await saveResults( processed );
return {
success: true,
resultId: result.id
};
} catch ( error ) {
throw new Error( `Workflow failed: ${error.message}` );
}
}
}
// workflow.ts
import { workflow, z } from '@outputai/core';
import { fetchUser, processData, saveResults } from './steps.js';
const WorkflowInputSchema = z.object( {
userId: z.string(),
processType: z.string()
} );
const WorkflowOutputSchema = z.object( {
success: z.boolean(),
resultId: z.string()
} );
export default workflow( {
name: 'dataProcessing',
description: 'Process user data and save results',
inputSchema: WorkflowInputSchema,
outputSchema: WorkflowOutputSchema,
fn: async ( input ) => {
// Get user data
const user = await fetchUser( { userId: input.userId } );
// Process the data
const processed = await processData( { user, processType: input.processType } );
// Save results
const result = await saveResults( { data: processed } );
return {
success: true,
resultId: result.id
};
}
} );
Find the workflow class in workflow.ts:
grep -E "class.*Workflow" src/workflows/my-workflow/workflow.ts
Convert TypeScript interfaces to Zod schemas:
// Before: TypeScript interface
interface WorkflowInput {
userId: string;
count: number;
options?: ProcessOptions;
}
// After: Zod schema
const WorkflowInputSchema = z.object( {
userId: z.string(),
count: z.number(),
options: ProcessOptionsSchema.optional()
} );
Replace class definition with workflow() call:
// Before
export class MyWorkflow implements Workflow<Input, Output> {
async execute( input: Input ): Promise<Output> {
// ...
}
}
// After
export default workflow( {
name: 'myWorkflow',
description: 'Description of what this workflow does',
inputSchema: InputSchema,
outputSchema: OutputSchema,
fn: async ( input ) => {
// ...
}
} );
Change direct function calls to object parameter calls:
// Before (Flow SDK)
const result = await someActivity( param1, param2, param3 );
// After (Output SDK)
const result = await someStep( { param1, param2, param3 } );
Remove error handling wrappers (see flow-error-try-catch-removal):
// Before
async execute( input ) {
try {
const result = await doWork( input );
return result;
} catch ( error ) {
throw new Error( error.message );
}
}
// After
fn: async ( input ) => {
const result = await doWork( { ...input } );
return result;
}
// Before
import { Workflow, WorkflowScope } from '@flow/sdk';
import { z } from 'zod';
// After
import { workflow, z } from '@outputai/core';
The workflow name must match the legacy name if other systems depend on it:
// Legacy system calls workflow by name 'userOnboarding'
export default workflow( {
name: 'userOnboarding', // Must match!
// ...
} );
Workflows should use export default:
// CORRECT
export default workflow( { ... } );
// WRONG
export const myWorkflow = workflow( { ... } );
Always include .js extension for local imports:
import { fetchUser, processData } from './steps.js';
import { WorkflowInputSchema } from './types.js';
Workflows can invoke other workflows directly:
// parent/workflow.ts
import { workflow, z } from '@outputai/core';
import childWorkflow from '../child/workflow.js';
export default workflow( {
name: 'parentWorkflow',
inputSchema: z.object( { data: z.string() } ),
outputSchema: z.object( { result: z.string() } ),
fn: async ( input ) => {
// Call child workflow like a step
const childResult = await childWorkflow( { input: input.data } );
return { result: childResult.output };
}
} );
// workflow.ts
import { Workflow, WorkflowScope, FatalError } from '@flow/sdk';
import {
validateInput,
fetchUserProfile,
generateReport,
sendNotification
} from './activities';
interface ReportInput {
userId: string;
reportType: 'daily' | 'weekly' | 'monthly';
includeCharts: boolean;
}
interface ReportOutput {
reportId: string;
downloadUrl: string;
generatedAt: string;
}
export class GenerateReportWorkflow implements Workflow<ReportInput, ReportOutput> {
async execute( input: ReportInput ): Promise<ReportOutput> {
try {
// Validate input
const validated = await validateInput( input );
// Fetch user profile
const profile = await fetchUserProfile( input.userId );
// Generate the report
const report = await generateReport(
profile,
validated.reportType,
validated.includeCharts
);
// Send notification
await sendNotification( profile.email, report.id );
return {
reportId: report.id,
downloadUrl: report.url,
generatedAt: new Date().toISOString()
};
} catch ( error ) {
throw new FatalError( `Report generation failed: ${error.message}` );
}
}
}
// workflow.ts
import { workflow, z } from '@outputai/core';
import {
validateInput,
fetchUserProfile,
generateReport,
sendNotification
} from './steps.js';
const ReportInputSchema = z.object( {
userId: z.string(),
reportType: z.enum( [ 'daily', 'weekly', 'monthly' ] ),
includeCharts: z.boolean()
} );
const ReportOutputSchema = z.object( {
reportId: z.string(),
downloadUrl: z.string(),
generatedAt: z.string()
} );
export default workflow( {
name: 'generateReport',
description: 'Generate user reports with optional charts',
inputSchema: ReportInputSchema,
outputSchema: ReportOutputSchema,
fn: async ( input ) => {
// Validate input
const validated = await validateInput( {
userId: input.userId,
reportType: input.reportType,
includeCharts: input.includeCharts
} );
// Fetch user profile
const profile = await fetchUserProfile( { userId: input.userId } );
// Generate the report
const report = await generateReport( {
profile,
reportType: validated.reportType,
includeCharts: validated.includeCharts
} );
// Send notification
await sendNotification( {
email: profile.email,
reportId: report.id
} );
return {
reportId: report.id,
downloadUrl: report.url,
generatedAt: new Date().toISOString()
};
}
} );
workflow() function@outputai/core.js extensionexport default usedflow-convert-activities-to-steps - Step conversionflow-error-try-catch-removal - Try-catch antipatternflow-error-zod-import - Zod import issuesflow-validation-checklist - Complete validation