Output SDK のワークフロー用に workflow.ts ファイルを作成します。 次のような場合に使用:ワークフロー関数を定義する、複数の処理ステップを統合・管理する、ワークフロー構造の問題を修正する。
Create workflow.ts files for Output SDK workflows. Use when defining workflow functions, orchestrating steps, or fixing workflow structure issues.
このスキルは、Output SDK ワークフロー用の workflow.ts ファイルを作成する方法を説明します。
ワークフローファイルには、ステップの実行を調整するメインのオーケストレーションロジックが含まれます。
// 正しい - @outputai/core からインポートする
import { workflow, z } from '@outputai/core';
// 誤り - zod から z をインポートしない
import { z } from 'zod';
すべてのインポートには .js 拡張子が必須です:
// 正しい
import { stepName } from './steps.js';
import { WorkflowInputSchema } from './types.js';
// 誤り - .js 拡張子が不足している
import { stepName } from './steps';
import { WorkflowInputSchema } from './types';
重要: ワークフローの fn は決定論的でなければなりません。
ワークフロー関数内での直接的な I/O 操作は禁止されています。
// 誤り - ワークフロー内で直接 I/O を実行している
export default workflow( {
// ...
fn: async input => {
const response = await fetch( 'https://api.example.com' ); // 絶対に行わないこと!
return response.json();
}
} );
// 正しい - I/O はステップに委譲する
export default workflow( {
// ...
fn: async input => {
const result = await fetchDataStep( input ); // I/O はステップで処理する
return result;
}
} );
関連スキル: output-error-nondeterminism
import { workflow, z } from '@outputai/core';
import { stepOne, stepTwo } from './steps.js';
import { WorkflowInputSchema, WorkflowOutput } from './types.js';
export default workflow( {
name: 'workflowName',
description: 'ワークフローの内容を簡潔に説明する文章',
inputSchema: WorkflowInputSchema,
outputSchema: z.object( { /* 出力の形状 */ } ),
fn: async ( input ): Promise<WorkflowOutput> => {
// ステップ呼び出しのオーケストレーション
const result = await stepOne( input );
const final = await stepTwo( result );
return final;
}
} );
ワークフローの一意な識別子。キャメルケースを使用します。
name: 'contentUtilsImageInfographicNano'
ワークフローの目的を人が読みやすい形で記述します。
description: 'Generate high-quality infographic images using AI-powered ideation'
ワークフローの入力を検証するためのスキーマ。types.ts からインポートします。
inputSchema: WorkflowInputSchema
関連スキル: output-dev-types-file
ワークフローの出力を検証するためのスキーマ。
outputSchema: z.object( {
results: z.array( z.string() ),
metadata: z.object( {
processedAt: z.string()
} )
} )
ワークフローの実行関数。決定論的でなければなりません。
fn: async ( input ): Promise<WorkflowOutput> => {
// ステップのオーケストレーションのみ - 直接 I/O は行わない
const result = await processStep( input );
return result;
}
実際のワークフロー(image_infographic_nano)をもとにした例:
import { workflow, z } from '@outputai/core';
import {
generateImageIdeas,
generateImages,
validateReferenceImages
} from './steps.js';
import {
WorkflowInput,
WorkflowInputSchema,
WorkflowOutput
} from './types.js';
import { normalizeReferenceImageUrls } from './utils.js';
export default workflow( {
name: 'contentUtilsImageInfographicNano',
description: 'Generate high-quality infographic images using Google Gemini 3 Pro Image model with AI-powered ideation',
inputSchema: WorkflowInputSchema,
outputSchema: z.array( z.string() ),
fn: async ( rawInput: WorkflowInput ): Promise<WorkflowOutput> => {
// 入力の前処理(純粋関数 - ワークフロー内で許可)
const input = {
...rawInput,
referenceImageUrls: normalizeReferenceImageUrls( rawInput.referenceImageUrls )
};
// 条件付きステップ実行
if ( input.referenceImageUrls && input.referenceImageUrls.length > 0 ) {
await validateReferenceImages( {
referenceImageUrls: input.referenceImageUrls as string[]
} );
}
// 逐次ステップ実行
const ideas = await generateImageIdeas( {
content: input.content,
numberOfIdeas: input.numberOfIdeas,
colorPalette: input.colorPalette,
artDirection: input.artDirection
} );
// 並列ステップ実行
const generations = await Promise.all(
ideas.map( idea =>
generateImages( {
input: {
referenceImageUrls: input.referenceImageUrls,
aspectRatio: input.aspectRatio,
resolution: input.resolution,
numberOfGenerations: input.numberOfGenerations,
storageNamespace: input.storageNamespace
},
prompt: idea
} )
)
);
return generations.flat();
}
} );
ステップを順番に実行する:
fn: async input => {
const step1Result = await stepOne( input );
const step2Result = await stepTwo( step1Result );
const step3Result = await stepThree( step2Result );
return step3Result;
}
独立したステップを並行して実行する:
fn: async input => {
const [ resultA, resultB, resultC ] = await Promise.all( [
stepA( input ),
stepB( input ),
stepC( input )
] );
return { resultA, resultB, resultC };
}
条件に基づいてステップを実行する:
fn: async input => {
if ( input.includeImages ) {
await processImages( input );
}
const result = input.mode === 'fast' ?
await quickProcess( input ) :
await detailedProcess( input );
return result;
}
複数のアイテムを並列処理する:
fn: async input => {
const results = await Promise.all(
input.items.map( item => processItem( { item } ) )
);
return { processedItems: results };
}
複数の変換処理を連鎖させる:
fn: async input => {
const extracted = await extractData( input );
const transformed = await transformData( extracted );
const validated = await validateData( transformed );
const enriched = await enrichData( validated );
return enriched;
}
workflow と z が @outputai/core からインポートされている.js 拡張子が付いているname がキャメルケースかつ一意であるdescription がワークフローの内容を明確に説明しているinputSchema が types.ts からインポートされているoutputSchema が実際の戻り値の型と一致しているfn が決定論的である(直接 I/O を行っていない)output-dev-code-style 参照)output-dev-step-function - I/O を処理するステップ関数の作成output-dev-evaluator-function - evaluator 関数でのステップ使用output-dev-types-file - 入出力スキーマの定義output-dev-folder-structure - workflow.ts の配置場所output-error-nondeterminism - 決定論的処理違反の修正output-error-zod-import - スキーマインポートに関する問題の修正output-dev-code-styleThis skill documents how to create workflow.ts files for Output SDK workflows. The workflow file contains the main orchestration logic that coordinates step execution.
// CORRECT - Import from @outputai/core
import { workflow, z } from '@outputai/core';
// WRONG - Never import z from zod
import { z } from 'zod';
All imports MUST use .js extension:
// CORRECT
import { stepName } from './steps.js';
import { WorkflowInputSchema } from './types.js';
// WRONG - Missing .js extension
import { stepName } from './steps';
import { WorkflowInputSchema } from './types';
CRITICAL: The workflow fn must be deterministic. No direct I/O operations are allowed in the workflow function.
// WRONG - Direct I/O in workflow
export default workflow( {
// ...
fn: async input => {
const response = await fetch( 'https://api.example.com' ); // NEVER do this!
return response.json();
}
} );
// CORRECT - Delegate I/O to steps
export default workflow( {
// ...
fn: async input => {
const result = await fetchDataStep( input ); // Steps handle I/O
return result;
}
} );
Related Skill: output-error-nondeterminism
import { workflow, z } from '@outputai/core';
import { stepOne, stepTwo } from './steps.js';
import { WorkflowInputSchema, WorkflowOutput } from './types.js';
export default workflow( {
name: 'workflowName',
description: 'Brief description of what the workflow does',
inputSchema: WorkflowInputSchema,
outputSchema: z.object( { /* output shape */ } ),
fn: async ( input ): Promise<WorkflowOutput> => {
// Orchestrate step calls
const result = await stepOne( input );
const final = await stepTwo( result );
return final;
}
} );
Unique identifier for the workflow. Use camelCase.
name: 'contentUtilsImageInfographicNano'
Human-readable description of the workflow's purpose.
description: 'Generate high-quality infographic images using AI-powered ideation'
Schema for validating workflow input. Import from types.ts.
inputSchema: WorkflowInputSchema
Related Skill: output-dev-types-file
Schema for validating workflow output.
outputSchema: z.object( {
results: z.array( z.string() ),
metadata: z.object( {
processedAt: z.string()
} )
} )
The workflow execution function. Must be deterministic.
fn: async ( input ): Promise<WorkflowOutput> => {
// Step orchestration only - no direct I/O
const result = await processStep( input );
return result;
}
Based on a real workflow (image_infographic_nano):
import { workflow, z } from '@outputai/core';
import {
generateImageIdeas,
generateImages,
validateReferenceImages
} from './steps.js';
import {
WorkflowInput,
WorkflowInputSchema,
WorkflowOutput
} from './types.js';
import { normalizeReferenceImageUrls } from './utils.js';
export default workflow( {
name: 'contentUtilsImageInfographicNano',
description: 'Generate high-quality infographic images using Google Gemini 3 Pro Image model with AI-powered ideation',
inputSchema: WorkflowInputSchema,
outputSchema: z.array( z.string() ),
fn: async ( rawInput: WorkflowInput ): Promise<WorkflowOutput> => {
// Pre-process input (pure function - OK in workflow)
const input = {
...rawInput,
referenceImageUrls: normalizeReferenceImageUrls( rawInput.referenceImageUrls )
};
// Conditional step execution
if ( input.referenceImageUrls && input.referenceImageUrls.length > 0 ) {
await validateReferenceImages( {
referenceImageUrls: input.referenceImageUrls as string[]
} );
}
// Sequential step execution
const ideas = await generateImageIdeas( {
content: input.content,
numberOfIdeas: input.numberOfIdeas,
colorPalette: input.colorPalette,
artDirection: input.artDirection
} );
// Parallel step execution
const generations = await Promise.all(
ideas.map( idea =>
generateImages( {
input: {
referenceImageUrls: input.referenceImageUrls,
aspectRatio: input.aspectRatio,
resolution: input.resolution,
numberOfGenerations: input.numberOfGenerations,
storageNamespace: input.storageNamespace
},
prompt: idea
} )
)
);
return generations.flat();
}
} );
Execute steps one after another:
fn: async input => {
const step1Result = await stepOne( input );
const step2Result = await stepTwo( step1Result );
const step3Result = await stepThree( step2Result );
return step3Result;
}
Execute independent steps concurrently:
fn: async input => {
const [ resultA, resultB, resultC ] = await Promise.all( [
stepA( input ),
stepB( input ),
stepC( input )
] );
return { resultA, resultB, resultC };
}
Execute steps based on conditions:
fn: async input => {
if ( input.includeImages ) {
await processImages( input );
}
const result = input.mode === 'fast' ?
await quickProcess( input ) :
await detailedProcess( input );
return result;
}
Process multiple items in parallel:
fn: async input => {
const results = await Promise.all(
input.items.map( item => processItem( { item } ) )
);
return { processedItems: results };
}
Chain multiple transformations:
fn: async input => {
const extracted = await extractData( input );
const transformed = await transformData( extracted );
const validated = await validateData( transformed );
const enriched = await enrichData( validated );
return enriched;
}
workflow and z imported from @outputai/core.js extensionname is camelCase and uniquedescription clearly explains the workflowinputSchema imported from types.tsoutputSchema matches actual return typefn is deterministic (no direct I/O)output-dev-step-function - Creating step functions that handle I/Ooutput-dev-evaluator-function - Using steps in evaluator functionsoutput-dev-types-file - Defining input/output schemasoutput-dev-folder-structure - Where workflow.ts belongsoutput-error-nondeterminism - Fixing determinism violationsoutput-error-zod-import - Fixing schema import issuesoutput-dev-code-style原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。