Bug: --no-chaining Flag Not Respected When Task Dependencies Present in worflow template files / npx claude-flow@alpha automation run-workflow
- Dominant language
- TypeScript
- Stars
- 72.7k
- Forks
- 8.6k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 83
Description
## Summary
The `--no-chaining` flag in claude-flow automation workflows is completely ignored when tasks contain `depends` arrays, causing automatic stream chaining with 200-300% token usage overhead and cascade failures.
## Environment
- **Claude-Flow Version**: @alpha (latest as of 2025-08-18)
- **Node.js Version**: v20.19.2
- **Operating System**: Linux (WSL2)
- **Command**: `npx claude-flow@alpha automation run-workflow`
## Expected Behavior
When using `--no-chaining` flag, tasks should NOT pipe stdout between dependent tasks, regardless of `depends` field presence. Tasks should execute independently using only their assigned prompts.
## Actual Behavior
Despite `--no-chaining` flag, tasks with `depends` arrays automatically trigger stream chaining, causing:
1. Complete stdout from previous task piped to next task's stdin
2. 200-300% token usage increase due to full context streaming
3. "No messages returned" errors when piped content is malformed
4. Cascade failures through dependent task chains
## Steps to Reproduce
### 1. Create Test Workflow File
**File**: `test-workflow.json`
```json
{
"name": "No-Chaining Bug Test",
"description": "Test workflow to reproduce --no-chaining flag bug",
"version": "1.0.0",
"variables": {
"session_id": "test_${timestamp}"
},
"agents": [
{
"id": "agent1",
"type": "researcher",
"name": "First Agent"
},
{
"id": "agent2",
"type": "coordinator",
"name": "Second Agent"
}
],
"tasks": [
{
"id": "task1",
"name": "First Task",
"type": "research",
"description": "Simple first task",
"claudePrompt": "You are Agent 1. Simply respond: 'Task 1 completed successfully'. Do not include any additional output.",
"assignTo": "agent1",
"timeout": 60000
},
{
"id": "task2",
"name": "Second Task",
"type": "coordination",
"description": "Dependent second task",
"claudePrompt": "You are Agent 2. Respond: 'Task 2 completed successfully'. Do not reference any input.",
"assignTo": "agent2",
"depends": ["task1"],
"timeout": 60000
}
],
"settings": {
"maxConcurrency": 1,
"timeout": 300000,
"failurePolicy": "continue-on-error"
}
}
```
### 2. Execute With --no-chaining Flag
```bash
npx claude-flow@alpha automation run-workflow test-workflow.json \
--claude \
--non-interactive \
--output-format stream-json \
--no-chaining \
--max-concurrency 1 \
--timeout 300000
```
### 3. Observe Logs
**Expected Output** (correct behavior):
```
🚀 Starting: First Task
● First Task - Starting Execution
⎿ Simple first task
⎿ Agent: agent1
🚀 Starting: Second Task
● Second Task - Starting Execution
⎿ Dependent second task
⎿ Agent: agent2
```
**Actual Output** (bug behavior):
```
🚀 Starting: First Task
● First Task - Starting Execution
⎿ Simple first task
⎿ Agent: agent1
🚀 Starting: Second Task
● Second Task - Starting Execution
⎿ Dependent second task
⎿ Agent: agent2
🔗 Enabling stream chaining from task1 to task2
🔗 Chaining: Piping output from previous agent to Second Agent
❌ [Second Agent] Error: No messages returned
```
## Root Cause Analysis
### Code Location
**File**: `src/cli/simple-commands/automation-executor.js`
**Line**: 1151
### Problematic Code
```javascript
// Line 1151-1158
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
// Get the output stream from the last dependency
const lastDependency = task.depends[task.depends.length - 1];
const dependencyStream = this.taskOutputStreams.get(lastDependency);
if (dependencyStream) {
console.log(` 🔗 Enabling stream chaining from ${lastDependency} to ${task.id}`);
chainOptions.inputStream = dependencyStream;
}
}
```
### Flag Parsing Analysis
The flag parsing works correctly:
1. **CLI Parsing**: `--no-chaining` sets `flags.chaining = false`
2. **runWorkflowCommand** (automation.js:292):
```javascript
enableChaining: options.chaining !== false // becomes: false !== false = false
```
3. **WorkflowExecutor Constructor** (automation-executor.js:50):
```javascript
this.enableChaining = options.enableChaining !== false; // becomes: false !== false = false
```
### The Bug
Despite `this.enableChaining = false`, the condition on line 1151 evaluates as:
- `this.enableChaining` = `false` ❌
- `this.options.outputFormat === 'stream-json'` = `true` ✅
- `task.depends?.length > 0` = `true` ✅
**However**, the logic `false && true && true = false` should prevent chaining, but it **still executes**. This suggests either:
1. The flag parsing chain is broken somewhere
2. There's another code path forcing chaining
3. The condition is being bypassed
## Impact Assessment
### Token Usage Impact
- **Without Dependencies**: ~5,000 tokens per workflow
- **With Stream Chaining**: ~15,000-20,000 tokens per workflow
- **Overhead**: 200-300% increase in token consumption
- **Cost Impact**: 2-3x increase in API costs
### Error Propagation
1. Task 1 completes successfully
2. Task 2 receives malformed stdin from Task 1's complete stdout
3. Claude CLI throws "No messages returned" error
4. Task 2 fails with exit code 1
5. Subsequent dependent tasks also fail in cascade
### Workflow Reliability
- **Success Rate with Dependencies**: ~33% (only first task succeeds)
- **Success Rate without Dependencies**: ~95% (all tasks independent)
## Workaround
Remove task dependencies and use memory-based coordination:
```json
{
"tasks": [
{
"id": "task1",
"claudePrompt": "Complete task and store result: npx claude-flow@alpha memory store session/task1/status 'completed'",
"assignTo": "agent1"
},
{
"id": "task2",
"claudePrompt": "Wait for task1: while true; do status=$(npx claude-flow@alpha memory retrieve session/task1/status 2>/dev/null || echo 'PENDING'); if [[ \"$status\" == \"completed\" ]]; then break; fi; sleep 5; done; echo 'Task 2 starting...'",
"assignTo": "agent2"
}
]
}
```
## Proposed Fix
### Option 1: Respect enableChaining Flag
```javascript
// Current (line 1151):
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
// Fixed:
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
```
*Note: This might already be correct. Need to investigate why it's not working.*
### Option 2: Add Explicit No-Chaining Check
```javascript
// More explicit fix:
if (this.enableChaining && !this.options.noChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
```
### Option 3: Debug Flag Parsing
Add debug logging to trace flag values:
```javascript
console.log(`DEBUG: enableChaining=${this.enableChaining}, noChaining=${this.options.noChaining}, outputFormat=${this.options.outputFormat}, depends=${task.depends?.length > 0}`);
```
## Additional Context
### Verification Command
The bug can be verified by searching for chaining messages:
```bash
npx claude-flow@alpha automation run-workflow test-workflow.json --no-chaining | grep -E "(Enabling stream chaining|Chaining:)"
```
**Expected**: No output (no chaining messages)
**Actual**: Shows chaining messages despite --no-chaining flag
### Related Code Files
- `src/cli/simple-commands/automation.js` - Flag parsing and WorkflowExecutor initialization
- `src/cli/simple-commands/automation-executor.js` - Stream chaining logic
- CLI argument parsing (need to investigate commander.js setup)
## Labels
`bug`, `automation`, `stream-chaining`, `flags`, `token-efficiency`, `workflow-execution`
Contributor guide
Research direction
Start with src/cli/simple-commands/automation.js to trace --no-chaining into WorkflowExecutor, then inspect the chaining condition around line 1151 in src/cli/simple-commands/automation-executor.js. Reproduce with the provided test-workflow.json and verification command, tracing the flag values and any alternate chaining path. Done means --no-chaining produces no chaining messages and dependent tasks do not receive the previous task's stdout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100