Skip to content

.NET: API inconsistency with Python - ConfigureSubWorkflow vs WorkflowExecutor for workflow composition #1502

Closed

Description

Summary

The .NET Agent Framework uses a different API pattern for workflow composition compared to the Python SDK, creating an inconsistency that hinders cross-platform development and documentation portability.
Python SDK (Simple & Explicit):

# Wrap workflow as an executor
sub_exec = WorkflowExecutor(sub, id="sub_workflow")

# Use in parent workflow
main_workflow = Workflow(...).add_edge(source, sub_exec)

.NET SDK (Less Discoverable):

// Extension method on Workflow instance
ExecutorIsh subWorkflowExecutor = subWorkflow.ConfigureSubWorkflow("subWorkflow");

// Use in parent workflow
var mainWorkflow = new WorkflowBuilder(...)
    .AddEdge(source, subWorkflowExecutor)

Issues:

  1. Different mental models - Python uses explicit wrapper class, .NET uses extension method
  2. Discoverability - Python's WorkflowExecutor is self-documenting, .NET's ConfigureSubWorkflow is hidden as extension method
  3. Documentation mismatch - Python migration guide references WorkflowExecutor, but it doesn't exist in .NET
  4. Naming inconsistency - Python uses "Executor" terminology, .NET uses "SubWorkflow" terminology
  5. API surface - Python's class-based approach is more explicit and testable

Current Behavior (.NET)

In .NET, workflows are converted to executors using an extension method:

// Build a sub-workflow
var subWorkflow = new WorkflowBuilder(uppercaseExecutor)
    .AddEdge(uppercaseExecutor, reverseExecutor)
    .AddEdge(reverseExecutor, appendExecutor)
    .WithOutputFrom(appendExecutor)
    .Build();

// ❓ Non-obvious: must call extension method
ExecutorIsh subWorkflowExecutor = subWorkflow.ConfigureSubWorkflow("subWorkflow");

// Use in parent workflow
var mainWorkflow = new WorkflowBuilder(prefixExecutor)
    .AddEdge(prefixExecutor, subWorkflowExecutor)
    .AddEdge(subWorkflowExecutor, postProcessExecutor)
    .Build();

Problems:

• ConfigureSubWorkflow is an extension method - not discoverable through IntelliSense on Workflow
• Lack of clarity: Method name doesn't clearly indicate "convert to executor"
• Returns opaque ExecutorIsh type instead of clearly typed wrapper
• No clear connection to "executor" concept (uses "SubWorkflow" terminology)


Python Behavior (Reference)
Python SDK uses an explicit wrapper class as documented in the migration guide:

from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat, Swarm
from autogen_agentchat.ui import Console

# Create sub-workflow
sub = Workflow()
sub.add_node(uppercase_executor)
sub.add_node(reverse_executor)
sub.add_edge(uppercase_executor, reverse_executor)

# ✅ Explicit wrapper class
**sub_exec = WorkflowExecutor(sub, id="sub_workflow")**

# Use in parent workflow
main = Workflow()
main.add_node(prefix_executor)
main.add_node(sub_exec)  # ✅ Clear that it's an executor
main.add_edge(prefix_executor, sub_exec)

Advantages:

  1. Explicit and discoverable - WorkflowExecutor class is easily found in API docs
  2. Self-documenting - Name clearly indicates "this wraps a workflow as an executor"
  3. Testable - Can mock/test WorkflowExecutor independently
  4. Consistent terminology - Uses "Executor" throughout
  5. Type-safe - Returns concrete WorkflowExecutor type, not opaque interface

Activity

  1. added
    .NETUsage: [Issues, PRs], Target: .Net
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 15, 2025
  2. changed the title [-].NET: API inconsistency with Python - ConfigureSubWorkflow vs WorkflowExecutor for workflow composition[/-] [+]Python: .NET: API inconsistency with Python - ConfigureSubWorkflow vs WorkflowExecutor for workflow composition[/+] on Oct 15, 2025
  3. changed the title [-]Python: .NET: API inconsistency with Python - ConfigureSubWorkflow vs WorkflowExecutor for workflow composition[/-] [+].NET: API inconsistency with Python - ConfigureSubWorkflow vs WorkflowExecutor for workflow composition[/+] on Oct 15, 2025
  4. added
    workflowsUsage: [Issues, PRs], Target: Workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 16, 2025
  5. lokitoth commented on Oct 22, 2025

    @lokitoth
    Contributor

    We do not allow the user to instantiate WorkflowExecutor as it depends on being factory-initialized to support all the various execution modes correctly. The burden of making it work in a cross-run shareable manner would be fairly significant.

    I expect this difference to remain, at least in the short term.

  6. joslat commented on Oct 22, 2025

    @joslat
    ContributorAuthor

    Hi Jacob Alber (@lokitoth), after looking into it, I agree with your concerns about direct instantiation breaking the factory pattern and cross-run shareability.

    But, The Real Problem Isn't the Class - It's the API Surface ;) - The issue isn't that WorkflowExecutor cannot exist - it's that users shouldn't directly instantiate it.

    However, we can achieve the Python SDK's discoverability benefits without exposing public constructors.

    Here is a proposed compromise:
    Add workflow.AsExecutor(id) as an extension method that internally maintains the factory pattern. This gives us:
    • ✅ Discoverable API (shows in IntelliSense)
    • ✅ Python-aligned naming ("Executor" terminology)
    • ✅ Factory pattern preserved (no direct instantiation)
    • ✅ Backward compatible (deprecate ConfigureSubWorkflow)

    Users get a better API surface, we keep architectural integrity. Win-win?

    // Current: Hidden
    var sub = workflow.ConfigureSubWorkflow("id");
    
    // Proposed: Discoverable
    var sub = workflow.AsExecutor("id");
    

    Would you consider this middle-ground approach?

  7. lokitoth commented on Oct 23, 2025

    @lokitoth
    Contributor

    Would you consider this middle-ground approach?

    Oh, I'd do more than consider: #1637 :)

  8. joslat commented on Oct 23, 2025

    @joslat
    ContributorAuthor

    I... like it! :)

  9. TaoChenOSU commented on Dec 5, 2025

    @TaoChenOSU
    Contributor

    Closed by #1637

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

Metadata

Metadata

Labels

.NETUsage: [Issues, PRs], Target: .NetpythonUsage: [Issues, PRs], Target: PythonworkflowsUsage: [Issues, PRs], Target: Workflows

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions