Skip to content

In-Browser Recursive Subagent Node Execution and Collapsible Nested Run Logs - #17

Open
Jacobcdsmith wants to merge 1 commit into
mainfrom
feat/recursive-subagent-execution-6836238995967300608
Open

In-Browser Recursive Subagent Node Execution and Collapsible Nested Run Logs#17
Jacobcdsmith wants to merge 1 commit into
mainfrom
feat/recursive-subagent-execution-6836238995967300608

Conversation

@Jacobcdsmith

@Jacobcdsmith Jacobcdsmith commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Added fully functioning recursive Subagent node execution. In-browser runFlow now resolves and executes child workflows, returning final sink output to the parent flow and collecting sub-steps. Inspector sidebar renders a dropdown select for other workflows/templates. Run Drawer renders collapsible, indented logs of the child sub-steps. Generated Python/JS code includes descriptive comments of subagents. Includes full unit tests.


PR created automatically by Jules for task 6836238995967300608 started by @Jacobcdsmith

Summary by CodeRabbit

  • New Features

    • Added workflow selection for subagent nodes, with templates and saved workflows available in a dropdown.
    • Subagents can now execute selected workflows recursively and return their final output.
    • Added nested execution logs with expandable details, outputs, errors, timing, and state snapshots.
    • Generated code now includes selected workflow metadata and graph statistics.
  • Bug Fixes

    • Added a fallback response when a configured workflow cannot be found.
  • Tests

    • Added coverage for nested execution, missing workflows, output propagation, and parent-flow execution.

…ted logs

- Update runFlow.ts to dynamically resolve subagent graph parameters from the Workflows and Templates Library and execute them recursively.
- Inject nested execution logs (subLogs) and return final sub-workflow state output to the parent state.last_output.
- Enhance Inspector.tsx to render a clean, reactive select dropdown populated with templates and custom workflows for subagent nodes, excluding the active workflow to prevent immediate self-recursion.
- Enhance the Run Drawer UI in Index.tsx to display indented, collapsible step-by-step subagent execution paths with individual nested state snapshots.
- Update codegen.ts for Python and JavaScript to generate informative, self-documenting comments mapping sub-workflow names, node counts, and edge counts.
- Add comprehensive Vitest unit tests in subagentExecution.test.ts verifying complete correctness of execution, inputs/outputs, error fallback, and log nesting.
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-flow-canvas Ready Ready Preview Jul 31, 2026 3:04pm

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Subagent nodes can select saved or template workflows, execute them recursively, and return nested logs. Generated code includes resolved workflow metadata. The Inspector excludes the active workflow, and the run-log UI displays nested execution details.

Changes

Subagent workflow execution

Layer / File(s) Summary
Workflow selection and code generation
frontend/src/flow/Inspector.tsx, frontend/src/flow/codegen.ts, frontend/src/pages/Index.tsx
Subagent fields list saved and template workflows, excluding the active workflow. Python and JavaScript generation includes workflow metadata or a fallback comment.
Recursive subagent execution
frontend/src/flow/runFlow.ts, frontend/src/test/subagentExecution.test.ts
Subagent nodes resolve workflows, parse input state, execute child flows recursively, preserve missing-workflow fallback behavior, and return nested logs. Tests cover direct and parent-flow execution.
Nested execution-log rendering
frontend/src/pages/Index.tsx
Run logs display expandable subagent steps, outputs, errors, timing, and state snapshots.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: emergent-agent-e1

Sequence Diagram(s)

sequenceDiagram
  participant ParentFlow
  participant SubagentNode
  participant ChildWorkflow
  participant RunLog
  ParentFlow->>SubagentNode: execute configured subagent
  SubagentNode->>ChildWorkflow: resolve and run with parsed input state
  ChildWorkflow-->>SubagentNode: return output and nested logs
  SubagentNode-->>ParentFlow: return output and subLogs
  ParentFlow->>RunLog: render parent and child execution details
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: recursive subagent execution and collapsible nested run logs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/recursive-subagent-execution-6836238995967300608

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
frontend/src/test/subagentExecution.test.ts (1)

1-229: 🩺 Stability & Availability | 🔵 Trivial

The coverage here is solid for the fallback and recursive-execution happy paths, and matches runNode's subagent case in frontend/src/flow/runFlow.ts. Once a cycle/depth guard is added there (see the critical comment on that file), add a test with two saved workflows that delegate to each other to confirm the guard throws a controlled error instead of recursing indefinitely.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/test/subagentExecution.test.ts` around lines 1 - 229, Add a test
in the subagent execution suite covering cyclic delegation: save two workflows
whose subagent nodes reference each other, execute the first through runNode or
runFlow, and assert the depth/cycle guard raises a controlled error rather than
recursing indefinitely. Keep the existing fallback and successful
nested-execution tests unchanged.
frontend/src/flow/Inspector.tsx (1)

50-78: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Hoist the workflow list computation out of the field loop.

allWorkflows and subagentWorkflowOptions are recomputed on every iteration of meta.configFields.map(...), for every node, on every render. loadWorkflows() reads and parses localStorage on each call. This work repeats even for non-subagent nodes and non-graph fields, and repeats on every keystroke in unrelated inputs (for example, the name field), since any onChange triggers a re-render of Inspector.

Compute this once per render, guarded by node.data.kind === "subagent", and memoize it.

♻️ Proposed refactor
+import { useMemo, useState } from "react";
 ...
 export function Inspector({ node, edges, nodes, gateways = [], activeWorkflowId, onChange, onDelete }: Props) {
   const [confirming, setConfirming] = useState(false);
+  const subagentWorkflowOptions = useMemo(() => {
+    if (!node || node.data.kind !== "subagent") return [];
+    return [...TEMPLATES, ...loadWorkflows()].filter((w) => w.id !== activeWorkflowId);
+  }, [node, activeWorkflowId]);

   if (!node) {
     return (
       ...
     );
   }
   ...
   {meta.configFields.map((f) => {
     const isSubagentGraph = node.data.kind === "subagent" && f.key === "graph";
-    const allWorkflows = [...TEMPLATES, ...loadWorkflows()];
-    const subagentWorkflowOptions = allWorkflows.filter((w) => w.id !== activeWorkflowId);

     return (

Note: useMemo must run unconditionally before the if (!node) early return, matching the existing useState placement, to keep the hook order stable across renders.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/flow/Inspector.tsx` around lines 50 - 78, Hoist the workflow
option computation out of the `meta.configFields.map` callback and memoize it
with `useMemo`, guarded by `node?.data.kind === "subagent"` so `loadWorkflows()`
runs only when needed and once per render inputs. Place this hook
unconditionally before the `if (!node)` early return, matching the existing
`useState` placement, then reuse its result for the `isSubagentGraph` select
options.
frontend/src/pages/Index.tsx (1)

2000-2071: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Nested log rendering handles only one level of subagent nesting.

This block only reads (l.output as any).subLogs. runNode's subagent case in frontend/src/flow/runFlow.ts returns subLogs, and each of those sub-log entries can itself carry output.subLogs if the child workflow contains its own subagent node. Those deeper levels have no expand affordance here, so a subagent-of-subagent chain silently loses visibility past the first level.

Separately, handleLogsExpandAll/handleLogsCollapseAll only patch keys from the top-level runLogs array. They don't set the sub-${uniqueKey} toggle or any nested subUniqueKey state-snapshot keys added here, so "Expand Snapshots" won't reveal subagent state or force-open the nested log view.

Consider extracting a recursive log-entry renderer (parameterized by depth/key-prefix) instead of duplicating the JSX for one hardcoded nesting level, and extend the expand/collapse handlers to walk into subLogs recursively.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/Index.tsx` around lines 2000 - 2071, The nested log UI
around the `subLogs` rendering only supports one level and the
expand-all/collapse-all handlers omit nested keys. Extract or implement a
recursive renderer for `RunLog` entries that discovers `output.subLogs` at every
depth, generates unique depth-aware keys, and preserves state snapshot toggles;
update `handleLogsExpandAll` and `handleLogsCollapseAll` to recursively traverse
all nested `subLogs` and set the corresponding log, sub-log, and snapshot
expansion keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/flow/runFlow.ts`:
- Around line 344-356: Forward the parent run’s stepDelay option in the
recursive runFlow call within the subworkflow execution path. Add opts.stepDelay
alongside the other propagated execution options so nested workflows preserve
the selected visualized stepping delay.
- Around line 315-366: Update RunOptions and the recursive delegation logic in
runFlow to track workflow IDs in the current delegation chain. Before recursing
for subWorkflow, detect whether its ID is already present and return the
existing simulated/fallback result instead of calling runFlow again; otherwise
pass a copied chain containing the subWorkflow ID into the recursive call.
Initialize the chain for top-level runs and preserve normal delegation for
workflows not yet visited.

---

Nitpick comments:
In `@frontend/src/flow/Inspector.tsx`:
- Around line 50-78: Hoist the workflow option computation out of the
`meta.configFields.map` callback and memoize it with `useMemo`, guarded by
`node?.data.kind === "subagent"` so `loadWorkflows()` runs only when needed and
once per render inputs. Place this hook unconditionally before the `if (!node)`
early return, matching the existing `useState` placement, then reuse its result
for the `isSubagentGraph` select options.

In `@frontend/src/pages/Index.tsx`:
- Around line 2000-2071: The nested log UI around the `subLogs` rendering only
supports one level and the expand-all/collapse-all handlers omit nested keys.
Extract or implement a recursive renderer for `RunLog` entries that discovers
`output.subLogs` at every depth, generates unique depth-aware keys, and
preserves state snapshot toggles; update `handleLogsExpandAll` and
`handleLogsCollapseAll` to recursively traverse all nested `subLogs` and set the
corresponding log, sub-log, and snapshot expansion keys.

In `@frontend/src/test/subagentExecution.test.ts`:
- Around line 1-229: Add a test in the subagent execution suite covering cyclic
delegation: save two workflows whose subagent nodes reference each other,
execute the first through runNode or runFlow, and assert the depth/cycle guard
raises a controlled error rather than recursing indefinitely. Keep the existing
fallback and successful nested-execution tests unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a408f6e-d417-42fc-9c44-b849f5d92078

📥 Commits

Reviewing files that changed from the base of the PR and between 0b7a689 and 8338426.

📒 Files selected for processing (5)
  • frontend/src/flow/Inspector.tsx
  • frontend/src/flow/codegen.ts
  • frontend/src/flow/runFlow.ts
  • frontend/src/pages/Index.tsx
  • frontend/src/test/subagentExecution.test.ts

Comment on lines +315 to +366
const allWorkflows = [...TEMPLATES, ...loadWorkflows()];
const subWorkflow = allWorkflows.find(w => w.id === cfg.graph || w.name === cfg.graph);

if (!subWorkflow) {
return {
simulated: true,
subagent: cfg.graph || "unknown",
input: interpolate(cfg.input || "", state, globalsList, secretsList),
note: "subagent workflow not found, fallback to simulated",
};
}

const rawInput = cfg.input || "";
const interpolatedInput = interpolate(rawInput, state, globalsList, secretsList);

let subInitialState: Record<string, unknown> = { query: interpolatedInput };
try {
const trimmed = interpolatedInput.trim();
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
const parsed = JSON.parse(trimmed);
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
subInitialState = parsed as Record<string, unknown>;
}
}
} catch {
// Fallback to simple query string
}

const subLogs: RunLog[] = [];
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});

const lastLogWithSnapshot = [...subResultLogs].reverse().find(l => l.stateSnapshot !== undefined);
const subFinalOutput = lastLogWithSnapshot?.stateSnapshot?.last_output ?? lastLogWithSnapshot?.output;

return {
simulated: true,
subagent: cfg.graph || "unknown",
input: interpolate(cfg.input || "", state, globalsList, secretsList),
note: "subagent execution is schematic",
subagent: subWorkflow.name,
subagentId: subWorkflow.id,
input: subInitialState,
output: subFinalOutput,
subLogs,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Add a cycle/depth guard before recursing into a subagent workflow.

RunOptions has no field to track which workflows are already on the current delegation chain, and the recursive call to runFlow (lines 344-356) has nothing that stops workflow A from delegating to workflow B, which delegates back to workflow A. Each runFlow call starts its own while loop and, for its own subagent nodes, recurses again with no bound other than the unrelated maxSteps (which only limits steps within a single flow, not the delegation depth across nested flows).

The Inspector's workflow selector (frontend/src/flow/Inspector.tsx lines 50-78) only excludes the currently active workflow id, so it blocks direct self-reference but not this indirect cycle: when editing workflow B, workflow A is still selectable even if A already delegates to B.

Left unguarded, a two-hop (or longer) delegation cycle causes unbounded recursion in the browser tab, exhausting the call stack and crashing or hanging the run.

Track the chain of workflow ids on RunOptions and reject re-entry into an already-visited workflow (or cap the delegation depth) before recursing.

🛡️ Proposed fix
 export interface RunOptions {
   nodes: Node<AgentNodeData>[];
   edges: Edge[];
   gateways: Gateway[];
   initialState?: Record<string, unknown>;
   maxSteps?: number;
   onLog?: (log: RunLog) => void;
   stepDelay?: number;
   onHumanApproval?: (req: {
     nodeId: string;
     name: string;
     prompt: string;
     channel: string;
   }) => Promise<string>;
   globals?: { key: string; value: string }[];
   secrets?: { key: string; value: string }[];
+  /** Internal: workflow ids already on the current subagent delegation chain, used to detect cycles. */
+  subagentChain?: string[];
 }
     case "subagent": {
       const allWorkflows = [...TEMPLATES, ...loadWorkflows()];
       const subWorkflow = allWorkflows.find(w => w.id === cfg.graph || w.name === cfg.graph);

       if (!subWorkflow) {
         return {
           simulated: true,
           subagent: cfg.graph || "unknown",
           input: interpolate(cfg.input || "", state, globalsList, secretsList),
           note: "subagent workflow not found, fallback to simulated",
         };
       }

+      const chain = opts.subagentChain ?? [];
+      const MAX_SUBAGENT_DEPTH = 10;
+      if (chain.includes(subWorkflow.id) || chain.length >= MAX_SUBAGENT_DEPTH) {
+        throw new Error(
+          `Subagent delegation cycle or depth limit reached: ${[...chain, subWorkflow.id].join(" → ")}`
+        );
+      }
+
       const rawInput = cfg.input || "";
       const interpolatedInput = interpolate(rawInput, state, globalsList, secretsList);
       ...
       const subResultLogs = await runFlow({
         nodes: subWorkflow.nodes,
         edges: subWorkflow.edges,
         gateways: opts.gateways,
         initialState: subInitialState,
         maxSteps: opts.maxSteps,
+        subagentChain: [...chain, subWorkflow.id],
         globals: globalsList,
         secrets: secretsList,
         onLog: (subLog) => {
           subLogs.push(subLog);
         },
         onHumanApproval: opts.onHumanApproval,
       });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const allWorkflows = [...TEMPLATES, ...loadWorkflows()];
const subWorkflow = allWorkflows.find(w => w.id === cfg.graph || w.name === cfg.graph);
if (!subWorkflow) {
return {
simulated: true,
subagent: cfg.graph || "unknown",
input: interpolate(cfg.input || "", state, globalsList, secretsList),
note: "subagent workflow not found, fallback to simulated",
};
}
const rawInput = cfg.input || "";
const interpolatedInput = interpolate(rawInput, state, globalsList, secretsList);
let subInitialState: Record<string, unknown> = { query: interpolatedInput };
try {
const trimmed = interpolatedInput.trim();
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
const parsed = JSON.parse(trimmed);
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
subInitialState = parsed as Record<string, unknown>;
}
}
} catch {
// Fallback to simple query string
}
const subLogs: RunLog[] = [];
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});
const lastLogWithSnapshot = [...subResultLogs].reverse().find(l => l.stateSnapshot !== undefined);
const subFinalOutput = lastLogWithSnapshot?.stateSnapshot?.last_output ?? lastLogWithSnapshot?.output;
return {
simulated: true,
subagent: cfg.graph || "unknown",
input: interpolate(cfg.input || "", state, globalsList, secretsList),
note: "subagent execution is schematic",
subagent: subWorkflow.name,
subagentId: subWorkflow.id,
input: subInitialState,
output: subFinalOutput,
subLogs,
const allWorkflows = [...TEMPLATES, ...loadWorkflows()];
const subWorkflow = allWorkflows.find(w => w.id === cfg.graph || w.name === cfg.graph);
if (!subWorkflow) {
return {
simulated: true,
subagent: cfg.graph || "unknown",
input: interpolate(cfg.input || "", state, globalsList, secretsList),
note: "subagent workflow not found, fallback to simulated",
};
}
const chain = opts.subagentChain ?? [];
const MAX_SUBAGENT_DEPTH = 10;
if (chain.includes(subWorkflow.id) || chain.length >= MAX_SUBAGENT_DEPTH) {
throw new Error(
`Subagent delegation cycle or depth limit reached: ${[...chain, subWorkflow.id].join(" → ")}`
);
}
const rawInput = cfg.input || "";
const interpolatedInput = interpolate(rawInput, state, globalsList, secretsList);
let subInitialState: Record<string, unknown> = { query: interpolatedInput };
try {
const trimmed = interpolatedInput.trim();
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
const parsed = JSON.parse(trimmed);
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
subInitialState = parsed as Record<string, unknown>;
}
}
} catch {
// Fallback to simple query string
}
const subLogs: RunLog[] = [];
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
subagentChain: [...chain, subWorkflow.id],
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});
const lastLogWithSnapshot = [...subResultLogs].reverse().find(l => l.stateSnapshot !== undefined);
const subFinalOutput = lastLogWithSnapshot?.stateSnapshot?.last_output ?? lastLogWithSnapshot?.output;
return {
subagent: subWorkflow.name,
subagentId: subWorkflow.id,
input: subInitialState,
output: subFinalOutput,
subLogs,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/flow/runFlow.ts` around lines 315 - 366, Update RunOptions and
the recursive delegation logic in runFlow to track workflow IDs in the current
delegation chain. Before recursing for subWorkflow, detect whether its ID is
already present and return the existing simulated/fallback result instead of
calling runFlow again; otherwise pass a copied chain containing the subWorkflow
ID into the recursive call. Initialize the chain for top-level runs and preserve
normal delegation for workflows not yet visited.

Comment on lines +344 to +356
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Forward stepDelay to the nested runFlow call.

The recursive runFlow call forwards gateways, maxSteps, globals, secrets, and onHumanApproval, but not stepDelay. When a user selects "Visualized (600ms)" for the parent run, the nested subagent workflow still executes at full speed, which is inconsistent with the parent's visualized stepping and with the newly added nested-log viewer's purpose of showing step-by-step subagent execution.

🔧 Proposed fix
       const subResultLogs = await runFlow({
         nodes: subWorkflow.nodes,
         edges: subWorkflow.edges,
         gateways: opts.gateways,
         initialState: subInitialState,
         maxSteps: opts.maxSteps,
+        stepDelay: opts.stepDelay,
         globals: globalsList,
         secrets: secretsList,
         onLog: (subLog) => {
           subLogs.push(subLog);
         },
         onHumanApproval: opts.onHumanApproval,
       });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});
const subResultLogs = await runFlow({
nodes: subWorkflow.nodes,
edges: subWorkflow.edges,
gateways: opts.gateways,
initialState: subInitialState,
maxSteps: opts.maxSteps,
stepDelay: opts.stepDelay,
globals: globalsList,
secrets: secretsList,
onLog: (subLog) => {
subLogs.push(subLog);
},
onHumanApproval: opts.onHumanApproval,
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/flow/runFlow.ts` around lines 344 - 356, Forward the parent
run’s stepDelay option in the recursive runFlow call within the subworkflow
execution path. Add opts.stepDelay alongside the other propagated execution
options so nested workflows preserve the selected visualized stepping delay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant