Skip to content

Add workflow builder page with routing and persistence #1101

Description

@geoffjay

Summary

Create the main workflow builder page that integrates the React Flow canvas, node palette, and serialization layer into a complete workflow composition experience. Add routing for the builder and wire up save/load to the orchestrator API.

Context

This issue brings together all the canvas infrastructure built in previous issues into a usable page. The builder page is where users create new workflows visually and edit existing ones. It serves as the primary integration point connecting the canvas components to the backend API.

Implementation Details

1. Workflow builder page

Create ui/src/pages/workflows/WorkflowBuilder.tsx:

Layout structure:

+--------------------------------------------------+
| Header: "Workflow Builder" | [Save] [Cancel]      |
+----------+---------------------------------------+
|          |                                       |
| Node     |     React Flow Canvas                 |
| Palette  |     (WorkflowCanvas component)        |
|          |                                       |
| [Triggers|                                       |
|  Agents] |                                       |
|          |                                       |
+----------+---------------------------------------+
| Status bar: validation errors, save status        |
+--------------------------------------------------+

Key features:

  • Full-height canvas layout (no scroll, canvas fills available space)
  • Node palette on the left (collapsible)
  • Header with workflow name input, save button, cancel button
  • Status bar showing validation errors and save progress
  • Unsaved changes indicator with browser beforeunload guard

2. State management

Use React state + React Flow hooks:

const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const [workflowName, setWorkflowName] = useState("");
const [isDirty, setIsDirty] = useState(false);
const [validationErrors, setValidationErrors] = useState<SerializationError[]>([]);

3. Save workflow

  • Click "Save" triggers validateGraph() from serialization layer
  • If valid: calls graphToWorkflows() to produce CreateWorkflowRequest[]
  • For new workflows: POST /workflows for each request
  • For existing workflows: PUT /workflows/{id} for updates, POST for new, DELETE for removed
  • Save canvas layout to localStorage
  • Show success toast on completion
  • Navigate to workflow list or detail on successful save

4. Load existing workflow

  • Route /workflows/:id/edit loads an existing workflow into the canvas
  • Fetch workflow via orchestratorClient.getWorkflow(id)
  • Fetch associated agent via orchestratorClient.listAgents()
  • Convert to graph via workflowsToGraph()
  • Restore layout from localStorage if available
  • Pre-populate workflow name field

5. Routing

Update ui/src/App.tsx:

<Route path="/workflows/builder" element={<WorkflowBuilder />} />
<Route path="/workflows/:id/edit" element={<WorkflowBuilder />} />

Update ui/src/pages/workflows/WorkflowList.tsx:

  • Change "New workflow" button to navigate to /workflows/builder
  • Add "Open in builder" action to workflow table rows

Update ui/src/pages/workflows/WorkflowDetail.tsx:

  • Add "Edit in builder" button in header

6. Connection validation

When users draw edges (via onConnect):

  • Only allow trigger -> agent connections (not trigger -> trigger or agent -> agent)
  • Prevent duplicate edges between same trigger and agent
  • Auto-assign default prompt template to new edges

7. Node configuration panel

When a node is selected, show a configuration panel (right side or modal):

  • Trigger nodes: form fields for the trigger type's configuration (e.g., owner/repo for GitHub, expression for cron)
  • Agent nodes: agent selector dropdown to change the target agent
  • Edges (when clicked): prompt template editor + poll interval

This reuses the existing PromptTemplateEditor component for edge config and adapts WorkflowForm field patterns for trigger config.

8. Tests

  • Builder page renders with canvas, palette, and header
  • Save button triggers serialization and API calls
  • Load existing workflow populates canvas
  • Connection validation prevents invalid edges
  • Unsaved changes guard triggers on navigation
  • Route parameters correctly control create vs. edit mode

Files to Create/Modify

  • ui/src/pages/workflows/WorkflowBuilder.tsx - new page
  • ui/src/pages/workflows/WorkflowBuilder.test.tsx - new tests
  • ui/src/App.tsx - add builder routes
  • ui/src/pages/workflows/WorkflowList.tsx - update "New" button
  • ui/src/pages/workflows/WorkflowDetail.tsx - add "Edit in builder" button
  • ui/src/layouts/Sidebar.tsx - optionally add builder nav item

Acceptance Criteria

  • Builder page renders with canvas, node palette, and header controls
  • Drag-and-drop from palette adds nodes to canvas
  • Drawing edges between trigger and agent nodes works
  • Connection validation prevents invalid edge types
  • Node selection opens configuration panel with appropriate fields
  • Edge click opens prompt template editor
  • Save serializes graph and calls workflow API
  • Load populates canvas from existing workflow(s)
  • Unsaved changes guard prevents accidental navigation
  • Routes work for both create (/workflows/builder) and edit (/workflows/:id/edit)
  • Existing workflow list/detail pages link to the builder
  • Tests cover save, load, and validation flows

Blocked By

Stack Base

Stack on: feature/autonomous-pipeline after #1099 and #1100 merge.

Metadata

Metadata

Assignees

No one assigned

    Labels

    complexity:largeLarge scope: 200+ lines, multiple filesenhancementNew feature or requestfrontendFrontend application codetriagedIssue has been triaged, ready for planning or implementationuiUser interface and frontend

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions