Skip to content

Attribute-Based Design

ALPHA - LIMITED ATTRIBUTES IN M1

Switchboard is currently in preview (v0.1.0-preview.62). In Milestone 1, only three internal attributes are available for extending the fluent API via source generators: [FlowAction], [Parameter], and [Transition].

Planned attributes (post-v1.0) include [ContactFlow], [Message], [Queue], and many others. See the Future section below.

This guide describes the current attribute model and the future roadmap.


Current: Flow Action Attributes (M1)

What's Available Now

The FlowActionGenerator uses three attributes to generate type-safe fluent methods:

  • [FlowAction] - Marks a class as a flow action
  • [Parameter] - Marks a property as a method parameter
  • [Transition] - Marks a property for transition routing

Example

csharp
using Switchboard.SourceGenerators.Attributes;

[FlowAction("PlayMessage")]
public class PlayMessageAction : FlowAction
{
    [Parameter]
    public string Text { get; set; }

    [Parameter]
    public string Voice { get; set; } = "Joanna";
}

Generated Extension Method:

csharp
public static IFlowBuilder PlayMessage(
    this IFlowBuilder builder,
    string text,
    string voice = "Joanna")
{
    var action = new PlayMessageAction
    {
        Identifier = $"play-message-{Guid.NewGuid().ToString()[..8]}",
        Text = text,
        Voice = voice
    };
    return builder.AddFlowAction(action);
}

Usage:

csharp
var flow = new FlowBuilder()
    .SetName("SalesFlow")
    .SetType(FlowType.ContactFlow)
    .PlayMessage("Welcome to sales")
    .TransferToQueue("SalesQueue")
    .Build();

Best Practices (Current)

1. Use Clear Action Names

csharp
// ✅ Good
[FlowAction("GetMenuChoice")]
public class GetMenuChoiceAction : FlowAction { }

// ❌ Poor
[FlowAction("Action1")]
public class Action1 : FlowAction { }

2. Mark Parameters Explicitly

Only properties with [Parameter] appear in the generated method signature:

csharp
[FlowAction("GetInput")]
public class GetInputAction : FlowAction
{
    [Parameter]
    public string Prompt { get; set; }  // In signature

    public string InternalId { get; set; }  // Not in signature
}

3. Provide Sensible Defaults

csharp
[FlowAction("Timeout")]
public class TimeoutAction : FlowAction
{
    [Parameter]
    public int Seconds { get; set; } = 5;  // Optional in generated method
}

4. Inherit from FlowAction

All action classes must inherit from FlowAction:

csharp
[FlowAction("MyAction")]
public class MyAction : FlowAction  // Required
{
    [Parameter]
    public string Data { get; set; }
}

Understanding the Fluent API

Since attribute-based flow definitions are not yet available (M1), use the fluent API directly:

Building Flows Fluently

csharp
var flow = new FlowBuilder()
    .SetName("CustomerService")
    .SetDescription("Main customer support flow")
    .SetType(FlowType.ContactFlow)
    .PlayPrompt(prompt =>
    {
        prompt.Text = "Welcome to customer service";
        prompt.Voice = "Matthew";
    })
    .GetCustomerInput(input =>
    {
        input.Primary.Prompt = "Press 1 for sales, 2 for support";
        input.MaxDigits = 1;
        input.TimeoutSeconds = 5;
    })
    .RouteByInput(router => router
        .When("sales", "1", sales => sales
            .PlayPrompt("Connecting to sales")
            .TransferToQueue("Sales")
            .Disconnect())
        .Otherwise(other => other
            .TransferToQueue("General")
            .Disconnect())
    )
    .Build();

Queues

csharp
var queue = new QueueBuilder()
    .SetName("SalesQueue")
    .SetDescription("Sales department queue")
    .SetMaxContacts(50)
    .AddTag("Department", "Sales")
    .Build();

Hours of Operation

csharp
var hours = new HoursOfOperation
{
    Name = "BusinessHours",
    TimeZone = "America/New_York"
};

hours.AddDayConfig(new HoursOfOperationConfig
{
    Day = DayOfWeek.Monday,
    StartTime = new TimeRange { Hours = 8, Minutes = 0 },
    EndTime = new TimeRange { Hours = 18, Minutes = 0 }
});

FUTURE: Planned Attributes (Post-v1.0)

Phase 2: ContactFlow Definition

Planned for a future milestone — DO NOT use these yet; they don't exist:

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[ContactFlow("SalesFlow", Description = "Sales inbound")]
public partial class SalesFlow : FlowDefinitionBase
{
    [Message("Welcome to sales")]
    public partial void Welcome();

    [TransferToQueue("Sales")]
    public partial void Transfer();
}

Phase 2: Message Attributes

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[Message("Hello world")]
public partial void PlayMessage();

[Message(ConfigKey = "welcomeMessage")]
public partial void PlayConfigurableMessage();

Phase 2: Routing Attributes

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[GetUserInput("Press 1 or 2", MaxDigits = 1)]
public partial Task<string> GetChoice();

[TransferToQueue("Support")]
public partial void TransferSupport();

Phase 2: Queue Definition

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[ContactFlow("MyFlow")]
[Queue("MyQueue", MaxContacts = 50)]
public partial class MyFlow { }

Phase 2: Hours of Operation Attributes

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[HoursOfOperation("BusinessHours", TimeZone = "America/New_York")]
[Weekday(DayOfWeek.Monday, "08:00", "18:00")]
public partial class MyFlow { }

Phase 3+: Advanced Attributes

csharp
// ❌ NOT IMPLEMENTED - DO NOT USE
[CheckAttribute(Attribute = "CustomerType", Value = "VIP")]
[SetAttribute(Key = "PriorityLevel", Value = "High")]
[InvokeLambda(FunctionArn = "arn:...")]
[CheckHours(HoursName = "BusinessHours")]
[PlayPrompt(PromptUri = "s3://...")]
[Disconnect]

Migration Path

Today (M1): Use the fluent API and [FlowAction] for extension methods.

Future (M2+): Attribute-based flow definitions will be available as the framework stabilizes.

See the roadmap for detailed phases.


See Also

Preview release - Licensing terms TBD before 1.0