Skip to content

CheckContactAttribute ​

Branch the flow based on contact attribute values. This is the primary method for conditional routing in Switchboard.

Signature ​

csharp
IFlowBuilder CheckContactAttribute(
    Action<CheckContactAttributeBuilder> configure,
    string? identifier = null)

Parameters ​

ParameterTypeRequiredDescription
configureAction<CheckContactAttributeBuilder>YesConfigure the attribute check
identifierstring?NoOptional identifier for the action

CheckContactAttributeBuilder Methods ​

MethodDescription
.Attribute(AttributeReference)Specify the attribute to check

After calling .Attribute(), comparison methods become available:

MethodDescription
.Equals(value, Action<IFlowBuilder>)Branch with inline flow when equals value
.Equals(value, string targetLabel)Jump to labeled action when equals value
.Equals(bool, Action<IFlowBuilder>)Branch with inline flow when equals boolean
.Equals(bool, string targetLabel)Jump to labeled action when equals boolean
.Equals(int, Action<IFlowBuilder>)Branch with inline flow when equals number
.Equals(int, string targetLabel)Jump to labeled action when equals number
.NotEquals(value, string targetLabel)Jump to labeled action when not equal
.Contains(substring, string targetLabel)Jump to labeled action when contains substring
.GreaterThan(value, string targetLabel)Jump to labeled action when greater than value
.LessThan(value, string targetLabel)Jump to labeled action when less than value
.Otherwise(Action<IFlowBuilder>)Default branch with inline flow
.Otherwise(string targetLabel)Jump to labeled action when no match

AttributeReference Types ​

Use the Attributes helper to reference attributes:

MethodDescriptionExample
Attributes.Contact("name")User-defined attribute$.Attributes.CustomerTier
Attributes.System(SystemAttributes.*)System attribute$.SystemEndpoint.Address
Attributes.External("name")Lambda response attribute$.External.StatusCode
Attributes.Lex("slotName")Lex bot slot$.Lex.Slots.ProductType

Examples ​

Simple String Comparison ​

csharp
Flow.Create("VIP Router")
    .CheckContactAttribute(check =>
    {
        check.Attribute(Attributes.Contact("CustomerTier"))
            .Equals("VIP", vip => vip
                .PlayPrompt("Welcome, valued customer!")
                .TransferToQueue("VIPSupport")
                .Disconnect())
            .Equals("Premium", premium => premium
                .TransferToQueue("PremiumSupport")
                .Disconnect())
            .Otherwise(standard => standard
                .TransferToQueue("General")
                .Disconnect());
    });

Boolean Check (Lambda Response) ​

csharp
Flow.Create("Authentication Flow")
    .InvokeLambda("ValidatePIN")
        .OnSuccess(success => success
            .CheckContactAttribute(check =>
            {
                check.Attribute(Attributes.External("Authenticated"))
                    .Equals(true, authenticated => authenticated
                        .PlayPrompt("Authentication successful.")
                        .TransferToQueue("Authenticated"))
                    .Otherwise(failed => failed
                        .PlayPrompt("Invalid PIN."));
            }))
        .OnError(error => error
            .PlayPrompt("Verification service unavailable."));

HTTP Status Code Check ​

csharp
Flow.Create("API Response Handler")
    .InvokeLambda("CustomerLookup")
        .OnSuccess(success => success
            .CheckContactAttribute(check =>
            {
                check.Attribute(Attributes.External("StatusCode"))
                    .Equals("200", found => found
                        .PlayPrompt("Customer found.")
                        .SetContactAttributes(attrs =>
                        {
                            attrs["CustomerName"] = Attributes.External("CustomerName");
                        }))
                    .Equals("404", notFound => notFound
                        .PlayPrompt("Customer not found."))
                    .Equals("500", serverError => serverError
                        .PlayPrompt("Service temporarily unavailable."))
                    .Otherwise(unexpected => unexpected
                        .PlayPrompt("Unexpected error occurred."));
            }))
        .OnError(error => error.Disconnect());

Numeric Comparison ​

csharp
Flow.Create("Balance Checker")
    .InvokeLambda("GetAccountBalance")
        .OnSuccess(s => s
            .SetContactAttributes(a => a["Balance"] = Attributes.External("Balance")))
        .OnError(e => e.Disconnect())
    .CheckContactAttribute(check =>
    {
        check.Attribute(Attributes.Contact("Balance"))
            .LessThan("0", negative => negative
                .PlayPrompt("Your account is overdrawn.")
                .TransferToQueue("Collections"))
            .LessThan("100", low => low
                .PlayPrompt("Your balance is low.")
                .TransferToQueue("Support"))
            .Otherwise(healthy => healthy
                .PlayPrompt("Your account is in good standing.")
                .TransferToQueue("General"));
    });

Language-Based Routing ​

csharp
Flow.Create("Multi-Language Flow")
    .CheckContactAttribute(check =>
    {
        check.Attribute(Attributes.Contact("Language"))
            .Equals("es", spanish => spanish
                .PlayPrompt("Bienvenido. Transfiriendo al equipo de español.")
                .TransferToQueue("SpanishSupport"))
            .Equals("fr", french => french
                .PlayPrompt("Bienvenue. Transfert vers l'équipe française.")
                .TransferToQueue("FrenchSupport"))
            .Otherwise(english => english
                .PlayPrompt("Welcome. Transferring to support.")
                .TransferToQueue("EnglishSupport"));
    });

Label-Based Targeting (Flat Flow Structure) ​

Use label-based targeting when you prefer a flat flow structure or need to reference actions defined elsewhere in the flow:

csharp
Flow.Create("Customer Input Router")
    .GetCustomerInput("Press 1 for Sales, 2 for Support, 3 for Billing.")
        .OnTimeout(timeout => timeout.Disconnect())
        .OnError(error => error.Disconnect())
        .OnDefault(def => def.Disconnect())

    // Route based on stored input using labels
    .CheckContactAttribute(check => check
        .Attribute("$.StoredCustomerInput")
        .Equals("1", "sales-handler")
        .Equals("2", "support-handler")
        .Equals("3", "billing-handler")
        .Otherwise("invalid-handler"))

    // Labeled handlers
    .JoinPoint("sales-handler")
    .PlayPrompt("Transferring to Sales.")
    .TransferToQueue("Sales")
    .Disconnect()

    .JoinPoint("support-handler")
    .PlayPrompt("Transferring to Support.")
    .TransferToQueue("Support")
    .Disconnect()

    .JoinPoint("billing-handler")
    .PlayPrompt("Transferring to Billing.")
    .TransferToQueue("Billing")
    .Disconnect()

    .JoinPoint("invalid-handler")
    .PlayPrompt("Invalid selection. Goodbye.")
    .Disconnect();

This approach is useful when:

  • Actions need to be shared across multiple branches
  • You want a flatter, more readable flow structure
  • You're migrating from legacy flow patterns

Complex Multi-Condition Flow ​

csharp
Flow.Create("Smart Router")
    // First check customer tier
    .CheckContactAttribute(tierCheck =>
    {
        tierCheck.Attribute(Attributes.Contact("CustomerTier"))
            .Equals("VIP", vip => vip
                // VIP customers get immediate queue
                .TransferToQueue("VIPSupport")
                .Disconnect())
            .Otherwise(nonVip => nonVip
                // Non-VIP: check if within business hours
                .CheckHoursOfOperation("BusinessHours")
                    .OnInHours(open => open
                        // During hours: check staffing
                        .CheckStaffingForQueue("Support", StaffingMetricType.Available)
                            .OnTrue(agentsAvailable => agentsAvailable
                                .TransferToQueue("Support"))
                            .OnFalse(noAgents => noAgents
                                .PlayPrompt("High call volume. Please hold.")
                                .TransferToQueue("Support"))
                            .OnError(e => e.TransferToQueue("Support")))
                    .OnOutOfHours(closed => closed
                        .PlayPrompt("We're closed.")
                        .Disconnect())
                    .OnError(e => e.TransferToQueue("Support")));
    });

Contains Check ​

csharp
Flow.Create("Keyword Router")
    .CheckContactAttribute(check =>
    {
        check.Attribute(Attributes.Contact("IssueDescription"))
            .Contains("urgent", urgent => urgent
                .TransferToQueue("UrgentSupport"))
            .Contains("billing", billing => billing
                .TransferToQueue("Billing"))
            .Contains("cancel", cancel => cancel
                .TransferToQueue("Retention"))
            .Otherwise(general => general
                .TransferToQueue("General"));
    });

Checking System Attributes ​

csharp
Flow.Create("Caller ID Router")
    .CheckContactAttribute(check =>
    {
        check.Attribute(Attributes.System(SystemAttributes.CustomerEndpointAddress))
            .Equals("+18005551234", knownCaller => knownCaller
                .PlayPrompt("Welcome back!")
                .TransferToQueue("ReturningCustomers"))
            .Otherwise(newCaller => newCaller
                .PlayPrompt("Thank you for calling.")
                .TransferToQueue("NewCustomers"));
    });

AWS Connect Block Type ​

This block generates the CheckContactAttributes action type in the exported flow JSON.

Comparison with Legacy Branch() ​

CheckContactAttribute replaces the deprecated Branch() method:

csharp
// ❌ Old deprecated way
.Branch(branch => branch
    .When(Attributes.Contact("Tier"), "VIP", vip => vip.TransferToQueue("VIP")))

// ✅ New preferred way
.CheckContactAttribute(check =>
{
    check.Attribute(Attributes.Contact("Tier"))
        .Equals("VIP", vip => vip.TransferToQueue("VIP"));
})

Best Practices ​

  1. Always include Otherwise - Handle unexpected values gracefully
  2. Check Lambda responses - Validate StatusCode before using data
  3. Use typed attributes - Use Attributes.* helpers for type safety
  4. Order conditions logically - Most specific first, Otherwise last
  5. Keep nesting shallow - Extract complex logic to helper methods

See Also ​

Preview release - Licensing terms TBD before 1.0