@output.ai/cli 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +6 -8
  2. package/dist/api/generated/api.d.ts +66 -0
  3. package/dist/api/generated/api.js +26 -0
  4. package/dist/assets/docker/docker-compose-dev.yml +9 -2
  5. package/dist/commands/workflow/runs/list.d.ts +14 -0
  6. package/dist/commands/workflow/runs/list.js +104 -0
  7. package/dist/services/coding_agents.js +180 -8
  8. package/dist/services/coding_agents.spec.js +54 -11
  9. package/dist/services/workflow_runs.d.ts +14 -0
  10. package/dist/services/workflow_runs.js +24 -0
  11. package/dist/templates/agent_instructions/AGENTS.md.template +13 -7
  12. package/dist/templates/agent_instructions/agents/{context_fetcher.md.template → workflow_context_fetcher.md.template} +1 -1
  13. package/dist/templates/agent_instructions/agents/workflow_debugger.md.template +98 -0
  14. package/dist/templates/agent_instructions/agents/workflow_planner.md.template +3 -3
  15. package/dist/templates/agent_instructions/agents/{prompt_writer.md.template → workflow_prompt_writer.md.template} +1 -1
  16. package/dist/templates/agent_instructions/agents/workflow_quality.md.template +2 -2
  17. package/dist/templates/agent_instructions/commands/build_workflow.md.template +2 -2
  18. package/dist/templates/agent_instructions/commands/debug_workflow.md.template +198 -0
  19. package/dist/templates/agent_instructions/commands/plan_workflow.md.template +2 -2
  20. package/dist/templates/agent_instructions/skills/output-error-direct-io/SKILL.md.template +249 -0
  21. package/dist/templates/agent_instructions/skills/output-error-http-client/SKILL.md.template +298 -0
  22. package/dist/templates/agent_instructions/skills/output-error-missing-schemas/SKILL.md.template +265 -0
  23. package/dist/templates/agent_instructions/skills/output-error-nondeterminism/SKILL.md.template +252 -0
  24. package/dist/templates/agent_instructions/skills/output-error-try-catch/SKILL.md.template +226 -0
  25. package/dist/templates/agent_instructions/skills/output-error-zod-import/SKILL.md.template +209 -0
  26. package/dist/templates/agent_instructions/skills/output-services-check/SKILL.md.template +128 -0
  27. package/dist/templates/agent_instructions/skills/output-workflow-list/SKILL.md.template +117 -0
  28. package/dist/templates/agent_instructions/skills/output-workflow-result/SKILL.md.template +199 -0
  29. package/dist/templates/agent_instructions/skills/output-workflow-run/SKILL.md.template +228 -0
  30. package/dist/templates/agent_instructions/skills/output-workflow-runs-list/SKILL.md.template +141 -0
  31. package/dist/templates/agent_instructions/skills/output-workflow-start/SKILL.md.template +201 -0
  32. package/dist/templates/agent_instructions/skills/output-workflow-status/SKILL.md.template +151 -0
  33. package/dist/templates/agent_instructions/skills/output-workflow-stop/SKILL.md.template +164 -0
  34. package/dist/templates/agent_instructions/skills/output-workflow-trace/SKILL.md.template +134 -0
  35. package/dist/templates/project/README.md.template +1 -1
  36. package/dist/templates/project/package.json.template +3 -2
  37. package/dist/utils/date_formatter.d.ts +15 -0
  38. package/dist/utils/date_formatter.js +31 -1
  39. package/package.json +1 -1
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Workflow runs service for fetching workflow run data from the API
3
+ */
4
+ import { getWorkflowRuns } from '#api/generated/api.js';
5
+ export async function fetchWorkflowRuns(options = {}) {
6
+ const params = {};
7
+ if (options.limit) {
8
+ params.limit = options.limit;
9
+ }
10
+ if (options.workflowType) {
11
+ params.workflowType = options.workflowType;
12
+ }
13
+ const response = await getWorkflowRuns(params);
14
+ if (!response) {
15
+ throw new Error('Failed to connect to API server. Is it running?');
16
+ }
17
+ if (!response.data) {
18
+ throw new Error('API returned invalid response (missing data)');
19
+ }
20
+ return {
21
+ runs: response.data.runs || [],
22
+ count: response.data.count || 0
23
+ };
24
+ }
@@ -205,15 +205,21 @@ throw new FatalError('Critical failure - do not retry');
205
205
  throw new ValidationError('Invalid input format');
206
206
  ```
207
207
 
208
- ## Agent System
208
+ ## Sub-Agents
209
209
 
210
210
  For workflow planning and implementation:
211
- - `.claude/agents/workflow_planner.md` - Workflow architecture specialist
212
- - `.claude/agents/workflow_quality.md` - Workflow quality and best practices specialist
213
- - `.claude/agents/prompt_writer.md` - Prompt file creation and review specialist
214
- - `.claude/agents/context_fetcher.md` - Efficient context retrieval (used by other agents)
215
- - `.claude/commands/plan_workflow.md` - Planning command
216
- - `.claude/commands/build_workflow.md` - Implementation command
211
+ - workflow-planner: `.claude/agents/workflow_planner.md` - Workflow architecture specialist
212
+ - workflow-quality: `.claude/agents/workflow_quality.md` - Workflow quality and best practices specialist
213
+ - workflow-prompt-writer: `.claude/agents/workflow_prompt_writer.md` - Prompt file creation and review specialist
214
+ - workflow-context-fetcher: `.claude/agents/workflow_context_fetcher.md` - Efficient context retrieval (used by other agents)
215
+ - workflow-debugger: `.claude/agents/workflow_debugger.md` - Workflow debugging specialist
216
+
217
+ ## Commands
218
+
219
+ For workflow planning and implementation:
220
+ - /plan_workflow: `.claude/commands/plan_workflow.md` - Planning command
221
+ - /build_workflow: `.claude/commands/build_workflow.md` - Implementation command
222
+ - /debug_workflow: `.claude/commands/debug_workflow.md` - Debugging command
217
223
 
218
224
  ## Configuration
219
225
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: context-fetcher
2
+ name: workflow-context-fetcher
3
3
  description: Use proactively to retrieve and extract relevant information from Output SDK project documentation files. Checks if content is already in context before returning.
4
4
  tools: Read, Grep, Glob
5
5
  model: haiku
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: workflow-debugger
3
+ description: Use this agent when you need to debug Output SDK workflows in local development. Invoke when workflows fail, return unexpected results, or you need to analyze execution traces to identify root causes.
4
+ model: opus
5
+ color: yellow
6
+ ---
7
+
8
+ # Output SDK Workflow Debugger Agent
9
+
10
+ ## Identity
11
+
12
+ You are an Output SDK debugging expert who specializes in diagnosing and resolving workflow execution issues in local development environments. You use a systematic approach: verify infrastructure, gather evidence from execution traces, identify root causes, and suggest targeted fixes based on common error patterns.
13
+
14
+ ## Context Retrieval
15
+
16
+ Use the `workflow-quality` subagent for:
17
+ - **Code Quality Guidance**: Import conventions, determinism rules, step boundaries
18
+ - **Best Practices**: Schema definitions, retry policies, error handling
19
+ - **Common Pitfalls**: Known issues and their solutions
20
+
21
+ Use the `workflow-context-fetcher` subagent for:
22
+ - **Project Structure**: Find workflow files in `src/workflows/*/`
23
+ - **Existing Patterns**: Examine similar implementations for comparison
24
+
25
+ ## CLI Commands for Debugging
26
+
27
+ For detailed command usage, Claude will automatically invoke the relevant skill.
28
+
29
+ ### Quick Reference
30
+
31
+ | Command | Purpose |
32
+ |---------|---------|
33
+ | `output dev` | Start development services |
34
+ | `output workflow list` | List available workflows |
35
+ | `output workflow runs list` | List execution history |
36
+ | `output workflow run` | Execute synchronously |
37
+ | `output workflow start` | Start asynchronously |
38
+ | `output workflow status` | Check execution status |
39
+ | `output workflow result` | Get execution result |
40
+ | `output workflow stop` | Stop running workflow |
41
+ | `output workflow debug` | Analyze execution trace |
42
+
43
+ ## Temporal UI
44
+
45
+ For visual workflow inspection and detailed execution timelines, access the Temporal Web UI at:
46
+
47
+ **http://localhost:8080**
48
+
49
+ The Temporal UI provides real-time visibility into workflow executions, event history, and task queues.
50
+
51
+ ## Systematic Debugging Approach
52
+
53
+ ### Step 1: Verify Infrastructure
54
+ Confirm Docker containers are running and services are active.
55
+ - **Skill**: `output-services-check`
56
+
57
+ ### Step 2: Gather Evidence
58
+ List recent runs and identify the failing workflow ID.
59
+ - **Skills**: `output-workflow-runs-list`, `output-workflow-trace`
60
+
61
+ ### Step 3: Analyze Trace
62
+ Examine the trace for error messages, failed steps, and I/O data.
63
+ - **Skill**: `output-workflow-trace`
64
+
65
+ ### Step 4: Apply Fix
66
+ Match error symptoms to solutions and verify the fix.
67
+ - **Skills**: `output-error-*` (matched by symptoms)
68
+
69
+ ## Example Interaction
70
+
71
+ **User**: "My workflow is failing but I don't know why. The run ID is abc123."
72
+
73
+ **Agent**: Let me help you debug this workflow. First, let's get the execution trace:
74
+
75
+ ```bash
76
+ output workflow debug abc123 --format json
77
+ ```
78
+
79
+ This will show us exactly where the workflow failed and what error occurred. While I analyze the trace, you can also check the Temporal UI at http://localhost:8080 for a visual timeline of the execution.
80
+
81
+ **User**: "The trace shows an error about incompatible schemas in step 'processData'."
82
+
83
+ **Agent**: This is likely the Zod import source issue. Check your step file - you're probably importing `z` from `zod` instead of `@output.ai/core`. These create different schema instances that aren't compatible.
84
+
85
+ Change:
86
+ ```typescript
87
+ import { z } from 'zod';
88
+ ```
89
+
90
+ To:
91
+ ```typescript
92
+ import { z } from '@output.ai/core';
93
+ ```
94
+
95
+ After making this change, run the workflow again with `output workflow run <workflowName>` to verify the fix.
96
+
97
+ ---
98
+ *This agent specializes in debugging Output SDK workflows in local development environments.*
@@ -14,12 +14,12 @@ You are a Output SDK workflow planning specialist who follows structured XML-bas
14
14
  Your workflow planning follows the structured process defined in `/plan_workflow` command with explicit numbered steps and validation checkpoints.
15
15
 
16
16
  ### Context Retrieval
17
- Use the `context-fetcher` subagent to retrieve documentation only if not already in context:
17
+ Use the `workflow-context-fetcher` subagent to retrieve documentation only if not already in context:
18
18
  - **Pre-Flight**: `.outputai/meta/pre_flight.md` - validation rules and smart defaults
19
19
  - **Post-Flight**: `.outputai/meta/post_flight.md` - completion checklist
20
20
  - **Existing Patterns**: `src/workflows/*/workflow.ts` - similar workflow patterns
21
21
 
22
- Use the `prompt-writer` subagent for:
22
+ Use the `workflow-prompt-writer` subagent for:
23
23
  - Creating and reviewing `.prompt` files
24
24
  - Liquid.js template syntax guidance
25
25
  - Provider/model configuration
@@ -64,7 +64,7 @@ Only request clarification for:
64
64
  - Specify workerModule service usage
65
65
 
66
66
  ### 🏗️ Step 5-6: Prompt & Orchestration Planning
67
- - Design LLM prompts with template variables (delegate to `prompt-writer` subagent for implementation)
67
+ - Design LLM prompts with template variables (delegate to `workflow-prompt-writer` subagent for implementation)
68
68
  - Define workflow execution logic step-by-step
69
69
  - Plan conditional logic and data flow
70
70
  - Generate TypeScript code templates
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: prompt-writer
2
+ name: workflow-prompt-writer
3
3
  description: Use this agent when writing, reviewing, or debugging LLM prompt files (.prompt). Specializes in Liquid.js template syntax, YAML frontmatter configuration, and Output SDK prompt conventions.
4
4
  tools: Read, Write, Edit, Grep, Glob
5
5
  model: sonnet
@@ -13,11 +13,11 @@ You are an Output SDK implementation expert who ensures workflow code follows be
13
13
 
14
14
  ## Context Retrieval
15
15
 
16
- Use the `context-fetcher` subagent to efficiently retrieve:
16
+ Use the `workflow-context-fetcher` subagent to efficiently retrieve:
17
17
  - **Existing Patterns**: Find similar implementations in `src/workflows/*/`
18
18
  - **Project Conventions**: Check `.outputai/AGENTS.md` for project-specific rules
19
19
 
20
- Use the `prompt-writer` subagent for:
20
+ Use the `workflow-prompt-writer` subagent for:
21
21
  - Creating new `.prompt` files
22
22
  - Reviewing or debugging prompt template syntax
23
23
  - Understanding Liquid.js syntax and YAML frontmatter
@@ -25,7 +25,7 @@ Implement the workflow described in the plan document, following Output SDK patt
25
25
 
26
26
  <process_flow>
27
27
 
28
- <step number="1" name="plan_analysis" subagent="context-fetcher">
28
+ <step number="1" name="plan_analysis" subagent="workflow-context-fetcher">
29
29
 
30
30
  ### Step 1: Plan Analysis
31
31
 
@@ -122,7 +122,7 @@ export const stepName = step( {
122
122
 
123
123
  </step>
124
124
 
125
- <step number="4" name="prompt_templates" subagent="prompt-writer">
125
+ <step number="4" name="prompt_templates" subagent="workflow-prompt-writer">
126
126
 
127
127
  ### Step 4: Prompt Templates (if needed)
128
128
 
@@ -0,0 +1,198 @@
1
+ ---
2
+ argument-hint: [problem-description-and-optional-workflow-id]
3
+ description: Debug Output SDK workflow issues
4
+ version: 0.0.1
5
+ model: claude-opus-4-1
6
+ ---
7
+
8
+ Your task is to systematically debug an Output SDK workflow issue in a local development environment.
9
+
10
+ The first argument is a textual description of the problem you're experiencing. If you have a specific workflow ID, include it in your description.
11
+
12
+ Use the todo tool to track your progress through the debugging process.
13
+
14
+ # Debugging Process
15
+
16
+ ## Overview
17
+
18
+ Follow a systematic approach to identify and resolve workflow execution issues: verify infrastructure, gather evidence, analyze traces, and apply targeted fixes.
19
+
20
+ <pre_flight_check>
21
+ EXECUTE: @.outputai/instructions/meta/pre_flight.md
22
+ </pre_flight_check>
23
+
24
+ <process_flow>
25
+
26
+ <step number="1" name="verify_services">
27
+
28
+ ### Step 1: Verify Services Running
29
+
30
+ Before debugging, confirm that all required services are operational. The `output-services-check` skill provides comprehensive guidance.
31
+
32
+ <verification_commands>
33
+ ```bash
34
+ # Check Docker containers are running
35
+ docker ps | grep output
36
+
37
+ # Verify Output services respond
38
+ curl -s http://localhost:3001/health || echo "API not responding"
39
+
40
+ # Check Temporal UI is accessible
41
+ curl -s http://localhost:8080 > /dev/null && echo "Temporal UI accessible" || echo "Temporal UI not accessible"
42
+ ```
43
+ </verification_commands>
44
+
45
+ <decision_tree>
46
+ IF docker_not_running:
47
+ RUN: docker compose up -d
48
+ WAIT: for services to start (30-60 seconds)
49
+ IF output_dev_not_running:
50
+ RUN: output dev
51
+ WAIT: for services to initialize
52
+ IF all_services_running:
53
+ PROCEED: to step 2
54
+ </decision_tree>
55
+
56
+ **Expected State**:
57
+ - Docker containers for `output` are running
58
+ - API server responds at `http://localhost:3001`
59
+ - Temporal UI accessible at `http://localhost:8080`
60
+
61
+ </step>
62
+
63
+ <step number="2" name="list_workflow_runs">
64
+
65
+ ### Step 2: List Workflow Runs
66
+
67
+ Identify the failing workflow execution by listing recent runs. The `output-workflow-runs-list` skill provides detailed filtering guidance.
68
+
69
+ <list_commands>
70
+ ```bash
71
+ # List all recent workflow runs
72
+ output workflow runs list
73
+
74
+ # Filter by specific workflow type (if known)
75
+ output workflow runs list <workflowName>
76
+
77
+ # Get detailed JSON output for analysis
78
+ output workflow runs list --format json
79
+
80
+ # Limit results to most recent
81
+ output workflow runs list --limit 10
82
+ ```
83
+ </list_commands>
84
+
85
+ <identification_criteria>
86
+ Look for:
87
+ - Status: FAILED or TERMINATED
88
+ - Recent timestamp matching when the issue occurred
89
+ - Workflow type matching the problem description
90
+ </identification_criteria>
91
+
92
+ <decision_tree>
93
+ IF user_provided_workflow_id:
94
+ USE: provided workflow ID
95
+ PROCEED: to step 3
96
+ IF failed_runs_found:
97
+ SELECT: most recent failed run
98
+ NOTE: workflow ID from output
99
+ PROCEED: to step 3
100
+ IF no_runs_found:
101
+ CHECK: workflow exists with `output workflow list`
102
+ IF workflow_not_found:
103
+ REPORT: workflow doesn't exist
104
+ SUGGEST: verify workflow name and location
105
+ ELSE:
106
+ SUGGEST: run the workflow with `output workflow run <name>`
107
+ </decision_tree>
108
+
109
+ </step>
110
+
111
+ <step number="3" name="debug_workflow" subagent="workflow-debugger">
112
+
113
+ ### Step 3: Debug Specific Workflow
114
+
115
+ Retrieve and analyze the execution trace for the identified workflow. The `output-workflow-trace` skill provides analysis techniques.
116
+
117
+ <debug_commands>
118
+ ```bash
119
+ # Display execution trace (text format)
120
+ output workflow debug <workflowId>
121
+
122
+ # Display full untruncated trace (JSON format) - recommended for detailed analysis
123
+ output workflow debug <workflowId> --format json
124
+ ```
125
+ </debug_commands>
126
+
127
+ **Tip**: Use `--format json` for complete trace data without truncation.
128
+
129
+ <analysis_checklist>
130
+ 1. Identify which step failed
131
+ 2. Examine the error message and stack trace
132
+ 3. Check input data passed to the failing step
133
+ 4. Check output data from preceding steps
134
+ 5. Look for patterns matching common error types
135
+ </analysis_checklist>
136
+
137
+ <temporal_ui_guidance>
138
+ For visual workflow inspection, open the Temporal Web UI at **http://localhost:8080**:
139
+ - Find your workflow execution by ID
140
+ - View the event history timeline
141
+ - Inspect individual step inputs and outputs
142
+ </temporal_ui_guidance>
143
+
144
+ </step>
145
+
146
+ <step number="4" name="suggest_fixes" subagent="workflow-quality">
147
+
148
+ ### Step 4: Suggest Fixes
149
+
150
+ Based on the trace analysis, identify the error pattern and suggest targeted fixes. Claude will invoke the relevant error skill based on symptoms.
151
+
152
+ <error_matching>
153
+
154
+ | Symptom | Skill |
155
+ |---------|-------|
156
+ | "incompatible schema" errors, type errors | `output-error-zod-import` |
157
+ | Replay failures, inconsistent results | `output-error-nondeterminism` |
158
+ | Retries not working, errors swallowed | `output-error-try-catch` |
159
+ | Type errors, undefined properties at step boundaries | `output-error-missing-schemas` |
160
+ | Workflow hangs, determinism errors | `output-error-direct-io` |
161
+ | Untraced requests, axios errors | `output-error-http-client` |
162
+
163
+ </error_matching>
164
+
165
+ <decision_tree>
166
+ IF error_matches_known_pattern:
167
+ INVOKE: relevant error skill for detailed fix
168
+ ELSE:
169
+ CONSULT: workflow-quality subagent for additional patterns
170
+ SUGGEST: Manual trace inspection in Temporal UI
171
+ </decision_tree>
172
+
173
+ <verification>
174
+ After applying fix:
175
+ ```bash
176
+ # Re-run the workflow to verify
177
+ output workflow run <workflowName> <input>
178
+
179
+ # Or start asynchronously and check result
180
+ output workflow start <workflowName> <input>
181
+ output workflow status <workflowId>
182
+ output workflow result <workflowId>
183
+ ```
184
+ </verification>
185
+
186
+ </step>
187
+
188
+ </process_flow>
189
+
190
+ <post_flight_check>
191
+ EXECUTE: @.outputai/instructions/meta/post_flight.md
192
+ </post_flight_check>
193
+
194
+ ---- START ----
195
+
196
+ Problem Description and Optional Workflow ID:
197
+
198
+ $ARGUMENTS
@@ -25,7 +25,7 @@ Generate detailed specifications for implementation of a new workflow.
25
25
 
26
26
  <process_flow>
27
27
 
28
- <step number="1" name="context_gathering" subagent="context-fetcher">
28
+ <step number="1" name="context_gathering" subagent="workflow-context-fetcher">
29
29
 
30
30
  ### Step 1: Context Gathering
31
31
 
@@ -130,7 +130,7 @@ export const sumValues = step( {
130
130
 
131
131
  </step>
132
132
 
133
- <step number="5" name="prompt_engineering" subagent="prompt-writer">
133
+ <step number="5" name="prompt_engineering" subagent="workflow-prompt-writer">
134
134
 
135
135
  ### Step 5: Prompt Engineering
136
136
 
@@ -0,0 +1,249 @@
1
+ ---
2
+ name: output-error-direct-io
3
+ description: Fix direct I/O in Output SDK workflow functions. Use when workflow hangs, returns undefined, shows "workflow must be deterministic" errors, or when HTTP/API calls are made directly in workflow code.
4
+ allowed-tools: [Bash, Read]
5
+ ---
6
+
7
+ # Fix Direct I/O in Workflow Functions
8
+
9
+ ## Overview
10
+
11
+ This skill helps diagnose and fix a critical error pattern where I/O operations (HTTP calls, database queries, file operations) are performed directly in workflow functions instead of in steps. This violates Temporal's determinism requirements.
12
+
13
+ ## When to Use This Skill
14
+
15
+ You're seeing:
16
+ - Workflow hangs indefinitely
17
+ - Undefined or empty responses
18
+ - "workflow must be deterministic" errors
19
+ - Network operations failing silently
20
+ - Timeouts without clear cause
21
+
22
+ ## Root Cause
23
+
24
+ Workflow functions must be **deterministic** - they should only orchestrate steps, not perform I/O directly. When you make HTTP calls, database queries, or any external operations directly in a workflow function:
25
+
26
+ 1. **Hangs**: The workflow may hang because I/O isn't properly handled
27
+ 2. **Determinism violations**: Temporal replays workflows, and I/O results differ
28
+ 3. **No retry logic**: Direct calls bypass Output SDK's retry mechanisms
29
+ 4. **No tracing**: Operations aren't recorded in the workflow trace
30
+
31
+ ## Symptoms
32
+
33
+ ### Direct fetch/axios in Workflow
34
+
35
+ ```typescript
36
+ // WRONG: I/O directly in workflow
37
+ export default workflow({
38
+ fn: async (input) => {
39
+ const response = await fetch('https://api.example.com/data'); // BAD!
40
+ const data = await response.json();
41
+ return { data };
42
+ }
43
+ });
44
+ ```
45
+
46
+ ### Direct Database Calls
47
+
48
+ ```typescript
49
+ // WRONG: Database I/O in workflow
50
+ export default workflow({
51
+ fn: async (input) => {
52
+ const user = await db.users.findById(input.userId); // BAD!
53
+ return { user };
54
+ }
55
+ });
56
+ ```
57
+
58
+ ### File System Operations
59
+
60
+ ```typescript
61
+ // WRONG: File I/O in workflow
62
+ import fs from 'fs/promises';
63
+
64
+ export default workflow({
65
+ fn: async (input) => {
66
+ const data = await fs.readFile(input.path, 'utf-8'); // BAD!
67
+ return { data };
68
+ }
69
+ });
70
+ ```
71
+
72
+ ## Solution
73
+
74
+ Move ALL I/O operations to step functions. Steps are designed to handle non-deterministic operations.
75
+
76
+ ### Before (Wrong)
77
+
78
+ ```typescript
79
+ export default workflow({
80
+ fn: async (input) => {
81
+ const response = await fetch('https://api.example.com/data');
82
+ const data = await response.json();
83
+ return { data };
84
+ }
85
+ });
86
+ ```
87
+
88
+ ### After (Correct)
89
+
90
+ ```typescript
91
+ import { z, step, workflow } from '@output.ai/core';
92
+ import { httpClient } from '@output.ai/http';
93
+
94
+ // Create a step for the I/O operation
95
+ export const fetchData = step({
96
+ name: 'fetchData',
97
+ inputSchema: z.object({
98
+ endpoint: z.string(),
99
+ }),
100
+ outputSchema: z.object({
101
+ data: z.unknown(),
102
+ }),
103
+ fn: async (input) => {
104
+ const client = httpClient({ prefixUrl: 'https://api.example.com' });
105
+ const data = await client.get(input.endpoint).json();
106
+ return { data };
107
+ },
108
+ });
109
+
110
+ // Workflow only orchestrates steps
111
+ export default workflow({
112
+ inputSchema: z.object({}),
113
+ outputSchema: z.object({ data: z.unknown() }),
114
+ fn: async (input) => {
115
+ const result = await fetchData({ endpoint: 'data' });
116
+ return result;
117
+ },
118
+ });
119
+ ```
120
+
121
+ ## Complete Example: Database Operation
122
+
123
+ ### Before (Wrong)
124
+
125
+ ```typescript
126
+ export default workflow({
127
+ fn: async (input) => {
128
+ const user = await prisma.user.findUnique({
129
+ where: { id: input.userId }
130
+ });
131
+ const orders = await prisma.order.findMany({
132
+ where: { userId: input.userId }
133
+ });
134
+ return { user, orders };
135
+ }
136
+ });
137
+ ```
138
+
139
+ ### After (Correct)
140
+
141
+ ```typescript
142
+ import { z, step, workflow } from '@output.ai/core';
143
+ import { prisma } from '../lib/db';
144
+
145
+ export const fetchUser = step({
146
+ name: 'fetchUser',
147
+ inputSchema: z.object({ userId: z.string() }),
148
+ outputSchema: z.object({
149
+ user: z.object({
150
+ id: z.string(),
151
+ name: z.string(),
152
+ email: z.string(),
153
+ }).nullable(),
154
+ }),
155
+ fn: async (input) => {
156
+ const user = await prisma.user.findUnique({
157
+ where: { id: input.userId }
158
+ });
159
+ return { user };
160
+ },
161
+ });
162
+
163
+ export const fetchOrders = step({
164
+ name: 'fetchOrders',
165
+ inputSchema: z.object({ userId: z.string() }),
166
+ outputSchema: z.object({
167
+ orders: z.array(z.object({
168
+ id: z.string(),
169
+ total: z.number(),
170
+ })),
171
+ }),
172
+ fn: async (input) => {
173
+ const orders = await prisma.order.findMany({
174
+ where: { userId: input.userId }
175
+ });
176
+ return { orders };
177
+ },
178
+ });
179
+
180
+ export default workflow({
181
+ inputSchema: z.object({ userId: z.string() }),
182
+ outputSchema: z.object({
183
+ user: z.unknown(),
184
+ orders: z.array(z.unknown()),
185
+ }),
186
+ fn: async (input) => {
187
+ const { user } = await fetchUser({ userId: input.userId });
188
+ const { orders } = await fetchOrders({ userId: input.userId });
189
+ return { user, orders };
190
+ },
191
+ });
192
+ ```
193
+
194
+ ## Finding Direct I/O in Workflows
195
+
196
+ Search for common I/O patterns in workflow files:
197
+
198
+ ```bash
199
+ # Find fetch calls
200
+ grep -rn "await fetch" src/workflows/
201
+
202
+ # Find axios calls
203
+ grep -rn "axios\." src/workflows/
204
+
205
+ # Find database operations
206
+ grep -rn "prisma\.\|db\.\|mongoose\." src/workflows/
207
+
208
+ # Find file system operations
209
+ grep -rn "fs\.\|readFile\|writeFile" src/workflows/
210
+ ```
211
+
212
+ Then review each match to see if it's in a workflow function vs a step function.
213
+
214
+ ## What CAN Be in Workflow Functions
215
+
216
+ Workflow functions should contain:
217
+ - **Step calls**: `await myStep(input)`
218
+ - **Orchestration logic**: conditionals, loops (over step calls)
219
+ - **Data transformation**: Pure functions on step results
220
+ - **Constants**: Static values and configuration
221
+
222
+ Workflow functions should NOT contain:
223
+ - HTTP/API calls
224
+ - Database operations
225
+ - File system operations
226
+ - External service calls
227
+ - Anything that talks to the network or filesystem
228
+
229
+ ## Verification
230
+
231
+ After moving I/O to steps:
232
+
233
+ 1. **Run the workflow**: `output workflow run <name> '<input>'`
234
+ 2. **Check the trace**: `output workflow debug <id> --format json`
235
+ 3. **Verify steps appear**: Look for your I/O steps in the trace
236
+ 4. **Confirm no errors**: No determinism warnings or hangs
237
+
238
+ ## Benefits of Steps for I/O
239
+
240
+ 1. **Retry logic**: Steps can be retried on failure
241
+ 2. **Tracing**: I/O operations appear in workflow traces
242
+ 3. **Timeouts**: Steps can have individual timeouts
243
+ 4. **Determinism**: Replays use recorded results
244
+ 5. **Debugging**: Clear visibility into what happened
245
+
246
+ ## Related Issues
247
+
248
+ - For HTTP client best practices, see `output-error-http-client`
249
+ - For non-determinism from other causes, see `output-error-nondeterminism`