Skip to content

feat: add visual builder + workspace mode to Burr UI#687

Open
andreahlert wants to merge 13 commits into
apache:mainfrom
andreahlert:feat/workspace-builder-lowcode
Open

feat: add visual builder + workspace mode to Burr UI#687
andreahlert wants to merge 13 commits into
apache:mainfrom
andreahlert:feat/workspace-builder-lowcode

Conversation

@andreahlert

@andreahlert andreahlert commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Building on #667 (Graph Builder by @skrawcz), this adds a workspace mode and significantly enhanced builder that turns Burr's UI into a development environment.

What's new

Visual Builder (enhanced)

  • 9 node types: Action, Input, Result, LLM Call, API Call, Code, Streaming, Loop, Router
  • Each type has specialized property editors (LLM: provider/model, API: url/method, Code: inline editor, Router: branch conditions)
  • Inline + button on edges (Activepieces-style) with searchable type picker
  • Recursive layout algorithm (replaces dagre) supporting loop arcs and router fan-out/fan-in
  • Node type picker with search bar and categories (I/O, Logic, Integrations)

Monaco Editor (split view)

  • Builder canvas on the left, VS Code-style editor on the right
  • Multi-file code generation: actions.py, app.py, run.py, requirements.txt
  • File explorer sidebar with tabs (open/close files)
  • Bidirectional sync: edit code and the graph updates, edit graph and the code updates
  • Full Ctrl+C/V/Z support in both canvas and editor

Project save/load

  • File menu (New, Save, Open, Download .py)
  • Projects persisted server-side in ~/.burr/builder_projects/
  • Ctrl+S to save

Workspace integration

  • Backend workspace router with file browsing, code viewing, and script execution (SSE streaming)
  • Link workspace directories to projects
  • Path traversal protection with workspace validation

Other improvements

  • Undo/redo with 50-state history
  • Keyboard shortcuts (Delete to remove nodes, Ctrl+C/V to copy/paste nodes)
  • Code generation includes proper imports, sanitized identifiers, and with_tracker()

Screenshots

Builder with nodes and generated code
02-builder-with-nodes

Node editor with LLM Call configuration
03-builder-node-editor

Searchable node type picker
04-builder-picker

Technical details

Backend (Python)

  • burr/tracking/server/workspace.py: new APIRouter with endpoints for file tree, file content, script execution (SSE), process management, workspace links, and builder project persistence
  • Modified run.py to mount workspace router, schema.py to add supports_workspace

Frontend (~6,700 new lines)

  • utils/: builderTypes, codeGenerator (9 node types + multi-file), codeParser (bidirectional sync), flowLayout (recursive layout), treeUtils (immutable tree ops), stateFlow
  • hooks/useBuilderState.ts: tree-based state with undo/redo, keyboard shortcuts, save/load
  • builder/: BuilderView (split layout), BuilderGraph (ReactFlow with custom node/edge types), NodeEditor, NodeTypePicker (portal-based), 4 node components, 5 edge components with inline + buttons
  • workspace/: FileExplorer, CodeViewer, RunTerminal, WorkspaceSelector
  • project/: ProjectWorkspaceView, ActivityBar, SidePanel, TabBar, TrackingSidePanel

Dependencies added

  • @monaco-editor/react (MIT)
  • @tanstack/react-query (MIT)
  • @xyflow/react (MIT)
  • react-joyride (MIT)

All MIT license, ASF Category A compatible.

How I tested

  • npx tsc --noEmit zero errors
  • Backend endpoints tested with curl
  • Manual E2E: create flow, add nodes via toolbar and inline +, edit properties, see code update, save/load projects

Checklist

  • PR has an informative and human-readable title
  • Changes are limited to a single goal
  • Code passed the pre-commit check
  • New functions are documented
  • Placeholder code is flagged / future TODOs are captured in comments

Comment thread burr/tracking/server/workspace.py
Comment thread burr/tracking/server/workspace.py
@skrawcz

skrawcz commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

@andreahlert I can't get this to run locally -- did you commit everything? otherwise see the CI failures.

@skrawcz

skrawcz commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Also need some example to load to help someone get started.

@andreahlert

Copy link
Copy Markdown
Collaborator Author

Thanks for reviewing. Didn't have the time to check it properly, I'll do it as soon as possible. Target: 03-30-2026

@andreahlert andreahlert self-assigned this Mar 28, 2026
@andreahlert

Copy link
Copy Markdown
Collaborator Author

Thanks for trying it out. Two things:

  1. Missing pieces: This PR is meant to be applied on top of feat: add visual Graph Builder tool to Burr UI #667 (your graph builder). On main alone, the builder route works but some of the other UI improvements (HomeView, SearchView, etc.) won't be there. The builder itself at /builder should load fine since all its deps are self-contained. I'll add a note about this in the PR description.

  2. Example graphs: Good call. I'll add a few pre-loaded examples (chatbot flow, data pipeline, agent with tools) that load from the File > Open menu so someone can see the builder in action without building from scratch.

Working on both now.

@JiwaniZakir JiwaniZakir left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In run.py, the shutdown sequence in lifespan calls await workspace.cleanup_processes() directly before await backend.lifespan(app).__anext__(), but there's no try/finally wrapping these calls. If cleanup_processes() raises an exception, the backend's own cleanup will be silently skipped, potentially leaking database connections or other resources. The backend shutdown should be guarded with a try/finally block regardless of what happens in workspace cleanup.

Additionally, supports_workspace=True is hardcoded unconditionally in _get_app_spec() — this means the UI will always advertise workspace support even if the feature is disabled or broken at runtime. This should be derived from a config flag or at least check that the workspace module initialized successfully, similar to how is_snapshotting_backend and is_annotations_backend are computed from the actual backend capabilities.

The _validate_workspace allowlist approach in workspace.py is a reasonable security boundary, but _read_links() is called on every file-browsing request with no caching. If the links file is read from disk on each API call under load, this could become a bottleneck — a short-lived in-process cache or memoization with invalidation on write would be worth considering.

@skrawcz

skrawcz commented Mar 29, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-03-29 at 09 25 22 Screenshot 2026-03-29 at 09 25 26

validated things load locally at least.

@andreahlert andreahlert added kind/feature Net-new functionality area/ui Burr UI (telemetry frontend) labels Mar 30, 2026

@elijahbenizzy elijahbenizzy 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.

Played around some -- looking great! Node types should probably have specific implementations but I think this is a good start to put out there.

andreahlert and others added 11 commits April 9, 2026 10:23
Adds a low-code visual builder with split-view Monaco editor,
workspace file browsing, and project persistence.

Builder features:
- 9 node types (Action, Input, Result, LLM Call, API Call, Code,
  Streaming, Loop, Router) with specialized property editors
- Inline + buttons on edges for inserting nodes (Activepieces-style)
- Recursive layout algorithm supporting loop arcs and router fan-out
- Monaco Editor with multi-file code generation (actions.py, app.py,
  run.py, requirements.txt)
- Bidirectional sync between graph and code
- Searchable node type picker with categories
- File menu with save/load projects, Ctrl+S support
- Undo/redo (50-state history), copy/paste, delete shortcuts
- Code generation with sanitized identifiers and proper imports

Workspace features:
- Backend router for file browsing, code viewing, script execution
  (SSE streaming), process management, and workspace-project linking
- Builder project persistence in ~/.burr/builder_projects/
- Path traversal protection with workspace validation

New dependencies (all MIT, ASF Category A):
- @monaco-editor/react
- @tanstack/react-query
- @xyflow/react
- react-joyride
- Remove unused imports/variables flagged by ESLint
- Replace regex literal with RegExp constructor to avoid no-control-regex
- Format workspace.py with black and isort
- Replace `as any` with proper types where possible
- Add eslint-disable comments for icon type maps (heroicons ForwardRef)
- Remove unused `id` from edge component destructures
- Remove unused `langMap` variable from BuilderView
This takes work from @jaeyow and apache#572.

Adds a drag-and-drop graph editor for designing Burr application graphs
visually and exporting as Python code or JSON.

Key changes:
- New /graph-builder route with full visual editor (ReactFlow v12)
- Migrate existing GraphView from reactflow v11 to @xyflow/react v12
- Remove reactflow and @tisoap/react-flow-smart-edge dependencies
- Per-node async/streaming toggles matching Burr's 4 action variants
- Python code generation with correct decorators and signatures
- 3 pre-built example graphs (MultiModal Chatbot, CRAG, Streaming)
- localStorage auto-save/restore of graph state
- Empty-state onboarding overlay and structured help sidebar
- Fix appcontainer layout for full-height content
Python (workspace.py):
- Module-level docstring describing all capabilities
- Docstrings on all Pydantic models, endpoints, and helper functions
- Documented security functions with Args/Returns/Raises

TypeScript:
- JSDoc on all exported types in builderTypes, codeGenerator, codeParser
- JSDoc on all tree operation functions in treeUtils
- JSDoc on layout algorithm functions in flowLayout
- JSDoc on useBuilderState hook
Remove the legacy react-query v3 package and standardize on
@tanstack/react-query v5 across all components. This fixes the
"No QueryClient set" error in BuilderView which was caused by
two separate QueryClient providers from different packages.
Wrap workspace.cleanup_processes() in try/finally so backend shutdown
always runs even if process cleanup fails. Derive supports_workspace
from workspace.is_available() instead of hardcoding True. Add in-process
cache to _read_links() to avoid disk reads on every file-browsing request.
@andreahlert andreahlert force-pushed the feat/workspace-builder-lowcode branch from 898f6be to 0fff68f Compare April 9, 2026 13:34
@andreahlert

Copy link
Copy Markdown
Collaborator Author

All review feedback addressed. Rebased clean on main, no conflicts.

@JiwaniZakir your three points: cleanup_processes() is wrapped in try/finally now so backend shutdown always runs, supports_workspace is derived from workspace.is_available() instead of hardcoded, and _read_links() has an in-process cache with invalidation on write.

@skrawcz docstrings on every function/class in workspace.py, including the inner ones. Examples were already in from the graph-builder merge.

@elijahbenizzy opened #735 to track the node type implementations as a follow-up. Agreed it's fine for the initial merge.

Ready for re-review whenever you get a chance.

@github-actions github-actions Bot added the pr/stale No activity for 14+ days after review label Apr 27, 2026
@github-actions

Copy link
Copy Markdown

This PR has been inactive for 17 days after receiving review feedback.
Converting to draft.

Please mark it as ready for review when you have addressed the comments.
If no activity occurs within 90 days, it will be closed automatically.

Combine event consumer cancellation from main with workspace cleanup
from this branch in the lifespan shutdown path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/tracking Telemetry, tracing, OpenTelemetry area/ui Burr UI (telemetry frontend) kind/feature Net-new functionality pr/stale No activity for 14+ days after review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants