/output-dev-workflow-function
Create workflow.ts files for Output SDK workflows. Use when defining workflow functions, orchestrating steps, or fixing workflow structure issues.
$ npx -y skills add growthxai/output --skill output-dev-workflow-function --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/output-dev-workflow-function
Context preview
The summary Claude sees to decide when to auto-load this skill.
Create workflow.ts files for Output SDK workflows. Use when defining workflow functions, orchestrating steps, or fixing workflow structure issues.
SKILL.md
output-dev-workflow-function.SKILL.mdname: output-dev-workflow-function
description: Create workflow.ts files for Output SDK workflows. Use when defining workflow functions, orchestrating steps, or fixing workflow structure issues.
allowed-tools: [Read, Write, Edit]
Creating workflow.ts Files
Overview
This skill documents how to create `workflow.ts` files for Output SDK workflows. The workflow file contains the main orchestration logic that coordinates step execution.
When to Use This Skill
- Creating a new workflow's main definition
- Understanding workflow structure requirements
- Debugging workflow orchestration issues
- Refactoring existing workflow logic
Critical Rules
1. Import Pattern
// CORRECT - Import from @outputai/core
import { workflow, z } from '@outputai/core';
// WRONG - Never import z from zod
import { z } from 'zod';2. ES Module Imports
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';3. Determinism Requirement
**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`
Basic Structure
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;
}
} );Required Properties
name (string)
Unique identifier for the workflow. Use camelCase.
name: 'contentUtilsImageInfographicNano'
description (string)
Human-readable description of the workflow's purpose.
description: 'Generate high-quality infographic images using AI-powered ideation'
inputSchema (Zod schema)
Schema for validating workflow input. Import from `types.ts`.
inputSchema: WorkflowInputSchema
**Related Skill**: `output-dev-types-file`
outputSchema (Zod schema)
Schema for validating workflow output.
outputSchema: z.object( {
results: z.array( z.string() ),
metadata: z.object( {
processedAt: z.string()
} )
} )fn (async function)
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;
}Complete Example
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();
}
} );Orchestration Patterns
Sequential Execution
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;
}Parallel Execution
Execute independent steps concurrently:
fn: async input => {
const [ resultA, resultB, resultC ] = await Promise.all( [
stepA( input ),
stepB( input ),
stepC( input )
] );
return { resultA, resultB, resultC };
}Conditional Execution
Execute steps based on conditions:
fn: async input => {
if ( input.includeImages ) {
await processImages( inputRead more
name: output-dev-workflow-function description: Create workflow.ts files for Output SDK workflows. Use when defining workflow functions, orchestrating steps, or fixing workflow structure issues. allowed-tools: [Read, Write, Edit]
Creating workflow.ts Files
Overview
This skill documents how to create `workflow.ts` files for Output SDK workflows. The workflow file contains the main orchestration logic that coordinates step execution.
When to Use This Skill
- Creating a new workflow's main definition
- Understanding workflow structure requirements
- Debugging workflow orchestration issues
- Refactoring existing workflow logic
Critical Rules
1. Import Pattern
// CORRECT - Import from @outputai/core
import { workflow, z } from '@outputai/core';
// WRONG - Never import z from zod
import { z } from 'zod';2. ES Module Imports
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';3. Determinism Requirement
**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`
Basic Structure
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;
}
} );Required Properties
name (string)
Unique identifier for the workflow. Use camelCase.
name: 'contentUtilsImageInfographicNano'
description (string)
Human-readable description of the workflow's purpose.
description: 'Generate high-quality infographic images using AI-powered ideation'
inputSchema (Zod schema)
Schema for validating workflow input. Import from `types.ts`.
inputSchema: WorkflowInputSchema
**Related Skill**: `output-dev-types-file`
outputSchema (Zod schema)
Schema for validating workflow output.
outputSchema: z.object( {
results: z.array( z.string() ),
metadata: z.object( {
processedAt: z.string()
} )
} )fn (async function)
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;
}Complete Example
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();
}
} );Orchestration Patterns
Sequential Execution
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;
}Parallel Execution
Execute independent steps concurrently:
fn: async input => {
const [ resultA, resultB, resultC ] = await Promise.all( [
stepA( input ),
stepB( input ),
stepC( input )
] );
return { resultA, resultB, resultC };
}Conditional Execution
Execute steps based on conditions:
fn: async input => {
if ( input.includeImages ) {
await processImages( inputThe open-source TypeScript framework for building AI workflows and agents. Designed for Claude Code — describe what you want, Claude builds it, with all the best practices already in place. One framework.
Repo: growthxai/output
Other skills on output.
- /llm-output-schema-constraints
Zod schema constraints that Anthropic rejects or silently ignores when sent as structured-output tool definitions via Output.object(). Use when writing or reviewing Zod schemas passed to Output.object(), or debugging structured-output validation errors.
Open skill - /prompt-file-provider-options
Guide to the providerOptions structure in .prompt files — decision tree for where an option goes, common mistakes, per-provider quick reference, and Anthropic prompt caching. Use when writing or reviewing .prompt file frontmatter (provider, model, providerOptions,
Open skill - /validate
Run lint, build, and tests to validate changes are correct
Open skill - /output-build-workflow
Implement an Output SDK workflow from a plan document. Use when the user asks to build, implement, or code a workflow from an existing plan, or after output-plan-workflow has produced a plan and the user is ready to build.
Open skill - /output-credentials-edit
View and edit encrypted credentials in an Output.ai project. Use when adding secrets, updating API keys, verifying credential values, or retrieving a specific credential.
Open skill - /output-credentials-env-vars
Wire encrypted credentials to environment variables using the credential: convention. Use when setting up LLM provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY) or any env var that should come from encrypted credentials.
Open skill

