Skip to content

.NET: [Feature/RFC]: DevUI visual authoring with declarative and code round-tripping #7398

Description

@joslat

Summary

Evolve DevUI developer mode from an execution/debugging surface into an opt-in local authoring environment for agents, harnesses, workflows, and subworkflows.

The proposed experience would let developers:

  • Discover and open existing agents, harness configurations, workflows, and subworkflows.
  • Create and edit them visually.
  • Edit the corresponding declarative YAML alongside the visual representation.
  • Generate deterministic, idiomatic C# and Python code, with an architecture that can add Go.
  • Import supported code patterns into the visual model.
  • Synchronize changes bidirectionally without overwriting custom application logic.
  • Validate, preview the source diff, hot-reload, run, and debug the edited entity in the same DevUI experience.

Why revisit this now?

This follows up on #1655 and its discussion of AutoGen Studio/n8n-style authoring, code generation, and UI-to-code synchronization. That issue was closed as completed, but DevUI currently provides workflow execution and visualization rather than the full visual-authoring and round-trip experience discussed in its comments.

The repository and framework have moved significantly since that discussion:

The prerequisite mentioned in #1655—stabilizing the declarative workflow design and bringing Python support alongside .NET—has therefore been met.

Related requests include #1686, #1462, and #3570.

Important scope boundary

Bidirectional synchronization should cover:

  1. Declarative definitions.
  2. Designer-managed generated code.
  3. A documented set of recognizable code-first patterns.

It should not promise lossless visual editing of arbitrary Turing-complete C#, Python, or Go. Dynamic or unsupported constructs should remain visible as opaque code-backed components with source navigation and explicit portability diagnostics.

That scope makes the feature deterministic and maintainable.

Proposed architecture: a common authoring model

Introduce a versioned, language-neutral Agent Framework Authoring IR as the synchronization pivot:

flowchart LR
    UI["DevUI visual designer"]
    IR["Versioned Agent Framework Authoring IR"]
    YAML["Declarative YAML"]
    CS["C# adapter (Roslyn)"]
    PY["Python adapter (LibCST)"]
    GO["Go adapter (go/ast + go/types)"]
    Runtime["Validate, reload, run, and debug"]

    UI <--> IR
    YAML <--> IR
    CS <--> IR
    PY <--> IR
    GO <--> IR
    IR --> Runtime
Loading

The GUI should not directly translate between YAML, C#, Python, and Go. Each representation maps through the same normalized IR.

The IR should contain:

  • Agents, models, instructions, tools, tool schemas, and resources.
  • Middleware and context providers.
  • Harness components such as planning, todos, memory, skills, approvals, loops, file access, and background agents.
  • Workflows, typed ports, executors, edges, conditions, and subworkflows.
  • Stable component IDs.
  • Source locations, symbols, and ownership information.
  • Portable configuration plus language-specific extension data.
  • Capability, validation, and portability diagnostics.

The existing declarative YAML should remain the primary portable representation. This proposal should not introduce a competing runtime DSL.

Source ownership modes

1. Declarative-owned

YAML is authoritative. Visual edits update YAML, and YAML edits update the visual model. Code is an optional generated artifact.

2. Designer-managed code

DevUI owns clearly marked generated files. Custom tools, executors, predicates, and middleware live in separate user-owned files and are referenced by symbol/import path.

3. Imported code

DevUI analyzes recognized construction patterns and offers safe edits for the supported subset. Unsupported logic appears as an opaque code node. A developer can explicitly choose Adopt into designer to create a managed declarative definition and generated source.

This ownership model prevents generated output from overwriting application code.

Synchronization method

Maintain three semantic snapshots per entity:

  1. The last synchronized base IR.
  2. The current source-derived IR.
  3. The edited DevUI IR.

Synchronize through a semantic three-way merge keyed by stable component IDs:

  1. Parse or project the source into IR.
  2. Apply UI edits as JSON Patch operations against the base revision.
  3. Automatically merge non-overlapping changes.
  4. Present property-level conflicts in a merge UI.
  5. Generate a complete source diff for review.
  6. Parse, validate, compile/type-check, and format the proposed output.
  7. Replace files atomically only after validation succeeds.
  8. Update the base revision and hot-reload the entity.

Use content hashes/ETags and If-Match semantics to prevent lost updates.

Semantic configuration should remain in YAML or code. Editor-only data such as positions, colors, viewport, and collapsed subworkflows can live in a committed .maf/design/*.json sidecar keyed by the same stable IDs.

Deterministic code generation

Code generation should be deterministic and template/AST based. AI-assisted conversion can be offered as an optional migration helper, but it should not be the synchronization engine.

.NET

  • Use Roslyn MSBuildWorkspace, SemanticModel, and SyntaxEditor for discovery, symbol resolution, diagnostics, and safe supported edits.
  • Use an incremental source generator or companion dotnet tool to generate *.g.cs from the Authoring IR/declarative files.
  • Generate a single explicit registration entry point and partial hooks for user implementations.
  • Compile the resulting project before applying the change.

Python

  • Use LibCST rather than only ast, so formatting and comments can be preserved when supported source is edited.
  • Generate a managed _maf_generated.py module.
  • Reference custom tools and predicates through qualified import paths.
  • Validate with Ruff and Pyright where available.
  • Treat dynamic factories, monkey-patching, and runtime-computed graphs as read-only/opaque unless adopted.

Go

  • Use go/packages, go/ast, go/types, and go/format.
  • Generate zz_generated.maf.go through go generate.
  • Keep user implementations in normal .go files and reference them by typed symbol.
  • Design the Authoring IR and capability protocol for Go from the start, while delivering the Go adapter after the initial .NET/Python implementation.

The Go SDK is currently in public preview in a separate repository, and DevUI/declarative workflows are not yet at parity: https://github.com/microsoft/agent-framework-go/blob/main/docs/dotnet-go-sdk-feature-comparison.md

Suggested technology stack

Area Technology Why
Designer Existing React, TypeScript, Vite, @xyflow/react, Zustand, Radix, Tailwind Reuses the frontend already shared by Python and .NET DevUI.
YAML/code editor Lazy-loaded Monaco Editor Mature code/diff editing, diagnostics, source navigation, and familiar VS Code experience.
Contracts Versioned JSON Schema and OpenAPI Language-neutral validation and schema-driven property forms.
Expressions Existing Power Fx model Avoids inventing another expression language and matches declarative workflows.
.NET adapter Roslyn Semantic understanding and syntax-preserving supported edits.
Python adapter LibCST + Ruff/Pyright Concrete-syntax preservation plus fast diagnostics.
Go adapter Standard Go analysis/format packages Idiomatic, deterministic, and toolchain-native.
Synchronization Stable IDs, ETags, JSON Patch, semantic three-way merge Prevents lost updates and avoids fragile line-based merging.

Capability-driven UI

Each runtime/language adapter should publish capability descriptors and JSON Schemas for the node/component types it supports.

DevUI can then:

  • Populate its palette dynamically.
  • Generate configuration forms from schemas.
  • Mark unsupported nodes for a selected target language.
  • Explain why a definition is not portable.
  • Avoid hard-coding every .NET, Python, and Go component in the frontend.

This is important for controlling the maintenance cost raised in #1655.

Security model

Visual authoring materially expands DevUI's trust boundary and should therefore be:

  • Disabled by default and enabled explicitly, for example with --authoring or AddDevUI(options => options.EnableAuthoring = true).
  • Restricted to an explicit project root with canonical path validation.
  • Loopback-only by default, consistent with DevUI's current security posture.
  • Diff-before-write, with no silent source modification.
  • Atomic and revision checked.
  • Static-analysis-first; importing a project should not execute arbitrary source merely to discover its graph.
  • Secret-reference-only: environment-variable and connection names may be edited, but secret values must never be returned to the browser or written into generated files.
  • Generator allowlist based: only registered component templates/adapters may emit code.

How this addresses the concerns raised in #1655

Concern Proposed response
A visual DSL cannot express all real-world logic Use the existing declarative model for the portable subset and retain code references/opaque nodes as escape hatches.
Arbitrary UI-authored logic is risky Generate only known typed components, require explicit diff approval, validate before writing, and keep authoring local/opt-in.
Keeping UI and code features synchronized is expensive Publish versioned capability descriptors from each runtime and drive the UI from schemas.
Production deployments ultimately use code Treat deterministic generated code as a first-class output with user-owned extension hooks.
Round-tripping arbitrary code is unreliable Clearly scope round-tripping to declarative and designer-managed patterns; import other code as read-only or partially editable.

Suggested delivery phases

Phase 1: Declarative workflow authoring

  • Visual create/open/edit/save for .NET and Python declarative workflows.
  • Live visual/YAML synchronization.
  • Schema and Power Fx validation.
  • Source diff, atomic save, hot reload, run, and debug.
  • Layout sidecars and stable IDs.

Phase 2: Agents and harnesses

  • Declarative agent editing.
  • Nested visualization for tools, middleware, context providers, and stable harness components.
  • Capability-driven configuration forms.

Phase 3: Managed C# and Python

  • Deterministic code generation.
  • Source maps and navigation.
  • Supported-pattern import and adoption.
  • Semantic conflict resolution.

Phase 4: Composition

  • Subworkflow authoring.
  • Expand/collapse and depth controls.
  • Reusable templates/components.
  • Cross-entity references and dependency validation.

Phase 5: Go

  • DevUI discovery/hosting adapter in agent-framework-go.
  • Go generator and supported-pattern importer.
  • Cross-language conformance tests against the Authoring IR.

MVP acceptance criteria

  • A developer can open an existing declarative workflow in DevUI, edit it visually, save it, and observe a valid YAML diff.
  • Editing the YAML updates the visual model without losing stable node identity.
  • The saved workflow loads and executes in both .NET and Python.
  • DevUI can generate deterministic C# and Python for the supported declarative subset.
  • Regenerating unchanged input produces byte-for-byte equivalent generated output after formatting.
  • Custom tools and conditions remain in user-owned files and survive regeneration.
  • Concurrent file/UI edits are detected and merged or shown as conflicts.
  • Unsupported constructs are preserved as opaque nodes and never silently dropped.
  • Secrets are neither returned to the browser nor emitted into generated source.
  • The authoring capability is opt-in and restricted to an explicit local project root.

Non-goals

  • A production low-code hosting platform.
  • Lossless editing of arbitrary C#, Python, or Go.
  • Executing arbitrary code merely to inspect a project.
  • Replacing code-first Agent Framework APIs.
  • Depending on an LLM for repeatable code generation or synchronization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETUsage: [Issues, PRs], Target: .NetpythonUsage: [Issues, PRs], Target: PythontriageUsage: [Issues], Target: All issues that still need to be triaged

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions