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…
Fix missing schema definitions in Output SDK steps. Use when seeing type errors, undefined properties at step boundaries, validation failures, or when step inputs/outputs aren't being properly typed.
Claude Code
$ npx -y skills add growthxai/output --skill output-error-missing-schemas --agent claude-code
Codex
$ npx skills add growthxai/output --skill output-error-missing-schemas -a codex -y
Cursor
$ npx skills add growthxai/output --skill output-error-missing-schemas -a cursor -y
Gemini CLI
$ npx skills add growthxai/output --skill output-error-missing-schemas -a gemini-cli -y
GitHub Copilot
$ npx skills add growthxai/output --skill output-error-missing-schemas -a github-copilot -y
OpenCode
$ npx skills add growthxai/output --skill output-error-missing-schemas -a opencode -y
Windsurf
$ npx skills add growthxai/output --skill output-error-missing-schemas -a windsurf -y
name: output-error-missing-schemas description: Fix missing schema definitions in Output SDK steps. Use when seeing type errors, undefined properties at step boundaries, validation failures, or when step inputs/outputs aren't being properly typed. allowed-tools: [Bash, Read]
This skill helps diagnose and fix issues caused by steps that lack explicit `inputSchema` or `outputSchema` definitions. Schemas are essential for type safety, validation, and proper data serialization between steps.
You're seeing:
Steps without explicit schemas:
// WRONG: No input validation
export const processData = step( {
name: 'processData',
// inputSchema: missing!
outputSchema: z.object( { result: z.string() } ),
fn: async input => {
return { result: input.value }; // input.value might be undefined!
}
} );// WRONG: No output validation
export const fetchData = step( {
name: 'fetchData',
inputSchema: z.object( { id: z.string() } ),
// outputSchema: missing!
fn: async input => {
return { data: await getFromApi( input.id ) }; // Output shape not validated
}
} );// WRONG: No validation at all
export const transformData = step( {
name: 'transformData',
// No schemas!
fn: async input => {
return transform( input );
}
} );Always define both `inputSchema` and `outputSchema` for every step:
import { z, step } from '@outputai/core';
export const processData = step( {
name: 'processData',
inputSchema: z.object( {
id: z.string(),
value: z.number(),
optional: z.string().optional()
} ),
outputSchema: z.object( {
result: z.string(),
processedAt: z.number()
} ),
fn: async input => {
// input is fully typed: { id: string, value: number, optional?: string }
return {
result: `Processed ${input.id}`,
processedAt: Date.now()
};
// output is validated against outputSchema
}
} );// Good: Clear, descriptive schema
inputSchema: z.object( {
userId: z.string().uuid(),
email: z.string().email(),
age: z.number().int().positive()
} )inputSchema: z.object( {
required: z.string(),
optional: z.string().optional(),
withDefault: z.string().default( 'fallback' )
} )// Define reusable schemas
const userSchema = z.object( {
id: z.string(),
name: z.string()
} );
const addressSchema = z.object( {
street: z.string(),
city: z.string()
} );
// Compose in step
inputSchema: z.object( {
user: userSchema,
address: addressSchema
} )inputSchema: z.object( {
items: z.array( z.object( {
id: z.string(),
quantity: z.number()
} ) ),
metadata: z.record( z.string() )
} )Search your codebase:
# Find step definitions
grep -rn "step({" src/workflows/
# Look for steps without inputSchema
grep -A5 "step({" src/workflows/ | grep -B2 "fn:"
# Check if schemas are present
grep -rn "inputSchema:" src/workflows/
grep -rn "outputSchema:" src/workflows/Review each step definition to ensure both schemas are present.
1. **Runtime Validation**: Catches data errors early 2. **Type Safety**: Full TypeScript inference in step functions 3. **Documentation**: Schemas document expected data shapes 4. **Serialization**: Ensures proper data serialization between steps 5. **Error Messages**: Clear validation errors when data is wrong
export const fetchUser = step( {
name: 'fetchUser',
inputSchema: z.object( {
userId: z.string()
} ),
outputSchema: z.object( {
user: z.object( {
id: z.string(),
name: z.string(),
email: z.string()
} ).nullable(), // Handle not found
found: z.boolean()
} ),
fn: async input => {
const user = await api.getUser( input.userId );
return { user, found: user !== null };
}
} );export const transformData = step( {
name: 'transformData',
inputSchema: z.object( {
raw: z.array( z.unknown() )
} ),
outputSchema: z.object( {
processed: z.array( z.object( {
id: z.string(),
value: z.number()
} ) ),
count: z.number()
} ),
fn: async input => {
const processed = input.raw.map( transformItem );
return { processed, count: processed.length };
}
} );For steps that don't return meaningful data:
export const logEvent = step( {
name: 'logEvent',
inputSchema: z.object( {
event: z.string(),
data: z.record( z.unknown() )
} ),
outputSchema: z.object( {
logged: z.literal( true )
} ),
fn: async input => {
await logger.log( input.event, input.data );
return { logged: true };
}
} );After adding schemas:
1. **TypeScript check**: `npm run output:worker:build` should pass without type errors 2. **Runtime test**: `npx output workflow run <name> --input '<input>'` should validate correctly 3. **Invalid input test**: Pass invalid data and verify validation errors appear
The 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.
Implement an Output SDK workflow from a plan document. Use when the user asks to build, implement, or code a workflow from an…
View, edit, and set encrypted credentials in an Output.ai project. Use when adding secrets, updating API keys, verifying…
Wire encrypted credentials to environment variables using the credential: convention. Use when setting up LLM provider keys…
Initialize encrypted credentials for an Output.ai project. Use when setting up credentials for the first time, adding…
Debug Output SDK workflow issues. Use when user reports a workflow failing, erroring, hanging, producing wrong results, or asks…
Use the Agent class for multi-step tool loops, conversation history, streaming progress, and reusable LLM agents. Use when…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.