with one click
flow-conventions-folder-structure
// Validate and fix folder structure for Output SDK workflows. Use to ensure migrated workflows follow the correct structure conventions.
// Validate and fix folder structure for Output SDK workflows. Use to ensure migrated workflows follow the correct structure conventions.
| name | flow-conventions-folder-structure |
| description | Validate and fix folder structure for Output SDK workflows. Use to ensure migrated workflows follow the correct structure conventions. |
| allowed-tools | ["Bash","Read","Grep","Glob"] |
This skill documents the required folder structure for Output SDK workflows and helps validate/fix structure issues after migration.
After Migration:
During Setup:
src/
āāā workflows/
āāā example_workflow/
āāā activities.ts # Activity functions
āāā helpers.ts # Optional helpers
āāā prompts.ts # JS prompt arrays
āāā prompts.xml # XML prompts
āāā readme.xml # Documentation
āāā types.ts # Type definitions
āāā workflow.ts # Workflow class
src/
āāā shared/ # Shared code across workflows
ā āāā clients/ # API clients (using @outputai/http)
ā āāā utils/ # Utility functions & helpers
ā āāā services/ # Business logic services
ā āāā steps/ # Shared steps (optional)
ā āāā evaluators/ # Shared evaluators (optional)
āāā workflows/
āāā example_workflow/
āāā workflow.ts # Workflow function (export default)
āāā steps.ts # OR steps/ folder for large workflows
āāā evaluators.ts # OR evaluators/ folder (optional)
āāā types.ts # Types + Zod schemas
āāā analyzeDocument@v1.prompt # Prompt files
āāā generateSummary@v1.prompt
āāā scenarios/ # Test input files
āāā basic_input.json
āāā full_options.json
The Output SDK enforces strict rules about where components can be defined:
| Component | Must be in |
|---|---|
step() calls | Files containing 'steps' in path |
evaluator() calls | Files containing 'evaluators' in path |
workflow() calls | workflow.ts file |
Examples:
src/workflows/my_workflow/steps.ts āsrc/workflows/my_workflow/steps/fetch_data.ts āsrc/shared/steps/common_steps.ts āsrc/workflows/my_workflow/helpers.ts ā (cannot contain step() calls)Steps and evaluators are Temporal activities with isolation constraints:
Steps CAN import from:
./utils.js, ./types.js, ./helpers.js./clients/pokeapi.js, ./lib/helpers.js../../shared/utils/*.js../../shared/clients/*.js../../shared/services/*.jsSteps CANNOT import:
Evaluators follow the same rules.
snake_case for folder names# Correct
user_onboarding/
generate_report/
analyze_document/
# Wrong
userOnboarding/
GenerateReport/
analyze-document/
| File | Naming | Purpose |
|---|---|---|
workflow.ts | Exact name | Workflow definition |
steps.ts | Exact name OR steps/ folder | All step definitions |
evaluators.ts | Exact name OR evaluators/ folder | Evaluator definitions |
types.ts | Exact name | Types and Zod schemas |
Format: {descriptiveName}@{version}.prompt
# Correct
analyzeDocument@v1.prompt
generateSummary@v1.prompt
extractEntities@v2.prompt
# Wrong
analyze.prompt # Missing version
analyzeDocument.txt # Wrong extension
analyze-document@v1.md # Wrong extension
Format: {descriptive_name}.json
# Correct
basic_input.json
full_options.json
edge_case_empty.json
question_ada_lovelace.json
# Wrong
test1.json # Not descriptive
BasicInput.json # Not snake_case
| File | Must Exist | Purpose |
|---|---|---|
workflow.ts | Yes | Workflow entry point |
steps.ts or steps/ | Yes (if steps exist) | Step definitions |
types.ts | Yes | Schemas and types |
| File/Folder | Optional | Purpose |
|---|---|---|
*.prompt | If LLM calls | Prompt templates |
scenarios/ | Recommended | Test inputs |
helpers.ts | If needed | Utility functions |
evaluators.ts or evaluators/ | If needed | Evaluator definitions |
| File | Action |
|---|---|
activities.ts | Rename to steps.ts or delete after conversion |
prompts.ts | Delete after converting to .prompt files |
prompts.xml | Delete after converting to .prompt files |
readme.xml | Can keep for reference or delete |
WORKFLOW="src/workflows/my_workflow"
# List all files
ls -la $WORKFLOW/
# Check for required files
[ -f "$WORKFLOW/workflow.ts" ] && echo "ā workflow.ts" || echo "ā workflow.ts missing"
[ -f "$WORKFLOW/steps.ts" ] || [ -d "$WORKFLOW/steps" ] && echo "ā steps" || echo "ā steps missing"
[ -f "$WORKFLOW/types.ts" ] && echo "ā types.ts" || echo "ā types.ts missing"
# Check for leftover files
[ -f "$WORKFLOW/activities.ts" ] && echo "ā activities.ts should be removed" || echo "ā No activities.ts"
[ -f "$WORKFLOW/prompts.ts" ] && echo "ā prompts.ts should be removed" || echo "ā No prompts.ts"
[ -f "$WORKFLOW/prompts.xml" ] && echo "ā prompts.xml should be removed" || echo "ā No prompts.xml"
# List workflow folders
ls -d src/workflows/*/
# Check for non-snake_case folders
ls -d src/workflows/*/ | while read dir; do
name=$(basename "$dir")
if [[ "$name" =~ [A-Z] ]] || [[ "$name" =~ "-" ]]; then
echo "ā Non-snake_case folder: $name"
fi
done
# List prompt files
ls src/workflows/my_workflow/*.prompt 2>/dev/null
# Check for version in prompt names
for f in src/workflows/my_workflow/*.prompt; do
if [[ ! "$f" =~ @v[0-9]+\.prompt$ ]]; then
echo "ā Missing version: $f"
fi
done
mv src/workflows/my_workflow/activities.ts src/workflows/my_workflow/steps.ts
mkdir -p src/workflows/my_workflow/scenarios
# Rename from camelCase to snake_case
mv src/workflows/userOnboarding src/workflows/user_onboarding
rm src/workflows/my_workflow/prompts.ts
rm src/workflows/my_workflow/prompts.xml
mkdir -p src/shared/clients
mkdir -p src/shared/utils
mkdir -p src/shared/services
src/workflows/userReport/
āāā activities.ts
āāā helpers.ts
āāā prompts.ts
āāā prompts.xml
āāā readme.xml
āāā types.ts
āāā workflow.ts
src/
āāā shared/
ā āāā clients/ # Move shared clients here
ā āāā api_client.ts
āāā workflows/
āāā user_report/ # Renamed to snake_case
āāā workflow.ts # Converted to workflow()
āāā steps.ts # Converted from activities.ts
āāā types.ts # Added Zod schemas
āāā generateReport@v1.prompt # Converted from prompts.ts
āāā formatOutput@v1.prompt
āāā scenarios/ # NEW
āāā daily_report.json
āāā weekly_report.json
āāā full_options.json
src/
āāā shared/ # Shared code across workflows
ā āāā clients/ # API clients
ā ā āāā gemini_client.ts
ā ā āāā jina_client.ts
ā āāā utils/ # Utility functions
ā ā āāā string_helpers.ts
ā āāā services/ # Business logic services
ā āāā content_service.ts
āāā workflows/
ā āāā user_onboarding/
ā ā āāā workflow.ts
ā ā āāā steps.ts
ā ā āāā types.ts
ā ā āāā welcome@v1.prompt
ā ā āāā scenarios/
ā āāā generate_report/
ā āāā workflow.ts
ā āāā steps/ # Folder-based for large workflows
ā ā āāā fetch_data.ts
ā ā āāā format.ts
ā āāā types.ts
ā āāā analyze@v1.prompt
ā āāā scenarios/
āāā index.ts # Exports
snake_caseworkflow.ts existssteps.ts or steps/ folder exists (if workflow has steps)types.ts existsname@version.prompt formatactivities.tsprompts.ts or prompts.xmlscenarios/ directory exists (recommended)snake_case.json formatsrc/shared/clients/flow-validation-checklist - Complete migration validationflow-create-scenario-files - Creating test scenariosflow-analyze-workflow-structure - Pre-migration analysisConvert 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.
Convert Flow SDK workflow class to Output SDK workflow() function. Use when migrating workflow.ts files from class-based to functional definitions.
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.