Edit

Share via


Declarative Workflows - Expressions and Variables

This document covers the expression language and variable management system used in declarative workflows.

Overview

Declarative workflows use a namespaced variable system and a PowerFx-like expression language to manage state and compute dynamic values. Understanding these concepts is essential for building effective workflows.

Note

Documentation for declarative workflows in .NET is coming soon. Please check back for updates.

Variable Namespaces

Variables in declarative workflows are organized into namespaces that determine their scope and purpose.

Available Namespaces

Namespace Description Access
Local.* Workflow-local variables Read/Write
Workflow.Inputs.* Input parameters passed to the workflow Read-only
Workflow.Outputs.* Values returned from the workflow Read/Write
System.* System-provided values Read-only
Agent.* Results from agent invocations Read-only

Local Variables

Use Local.* for temporary values during workflow execution:

actions:
  - kind: SetVariable
    variable: Local.counter
    value: 0

  - kind: SetVariable
    variable: Local.message
    value: "Processing..."

  - kind: SetVariable
    variable: Local.items
    value: []

Workflow Inputs

Access input parameters using Workflow.Inputs.*:

name: process-order
inputs:
  orderId:
    type: string
    description: The order ID to process
  quantity:
    type: integer
    description: Number of items

actions:
  - kind: SetVariable
    variable: Local.order
    value: =Workflow.Inputs.orderId

  - kind: SetVariable
    variable: Local.total
    value: =Workflow.Inputs.quantity

Workflow Outputs

Store results in Workflow.Outputs.* to return values from the workflow:

actions:
  - kind: SetVariable
    variable: Local.result
    value: "Calculation complete"

  - kind: SetVariable
    variable: Workflow.Outputs.status
    value: success

  - kind: SetVariable
    variable: Workflow.Outputs.message
    value: =Local.result

System Variables

Access system-provided values through the System.* namespace:

Variable Description
System.ConversationId Current conversation identifier
System.LastMessage The most recent message
System.Timestamp Current timestamp
actions:
  - kind: SetVariable
    variable: Local.conversationRef
    value: =System.ConversationId

Agent Variables

After invoking an agent, access response data through Agent.*:

actions:
  - kind: InvokeAzureAgent
    id: call_assistant
    agent:
      name: MyAgent
    output:
      responseObject: Local.AgentResult

  # Access agent response
  - kind: SendActivity
    activity:
      text: =Local.AgentResult.text

Expression Language

Values prefixed with = are evaluated as expressions at runtime.

Literal vs. Expression Values

# Literal string (stored as-is)
value: Hello World

# Expression (evaluated at runtime)
value: =Concat("Hello ", Workflow.Inputs.name)

# Literal number
value: 42

# Expression returning a number
value: =Workflow.Inputs.quantity * 2

String Operations

Concat

Concatenate multiple strings:

value: =Concat("Hello, ", Workflow.Inputs.name, "!")
# Result: "Hello, Alice!" (if Workflow.Inputs.name is "Alice")

value: =Concat(Local.firstName, " ", Local.lastName)
# Result: "John Doe" (if firstName is "John" and lastName is "Doe")

IsBlank

Check if a value is empty or undefined:

condition: =IsBlank(Workflow.Inputs.optionalParam)
# Returns true if the parameter is not provided

value: =If(IsBlank(Workflow.Inputs.name), "Guest", Workflow.Inputs.name)
# Returns "Guest" if name is blank, otherwise returns the name

Conditional Expressions

If Function

Return different values based on a condition:

value: =If(Workflow.Inputs.age < 18, "minor", "adult")

value: =If(Local.count > 0, "Items found", "No items")

# Nested conditions
value: =If(Workflow.Inputs.role = "admin", "Full access", If(Workflow.Inputs.role = "user", "Limited access", "No access"))

Logical Operations

Comparison Operators

Operator Description Example
= Equal to =Workflow.Inputs.status = "active"
<> Not equal to =Workflow.Inputs.status <> "deleted"
< Less than =Workflow.Inputs.age < 18
> Greater than =Workflow.Inputs.count > 0
<= Less than or equal =Workflow.Inputs.score <= 100
>= Greater than or equal =Workflow.Inputs.quantity >= 1

Boolean Functions

# Or - returns true if any condition is true
condition: =Or(Workflow.Inputs.role = "admin", Workflow.Inputs.role = "moderator")

# And - returns true if all conditions are true
condition: =And(Workflow.Inputs.age >= 18, Workflow.Inputs.hasConsent)

# Not - negates a condition
condition: =Not(IsBlank(Workflow.Inputs.email))

Mathematical Operations

# Addition
value: =Workflow.Inputs.price + Workflow.Inputs.tax

# Subtraction
value: =Workflow.Inputs.total - Workflow.Inputs.discount

# Multiplication
value: =Workflow.Inputs.quantity * Workflow.Inputs.unitPrice

# Division
value: =Workflow.Inputs.total / Workflow.Inputs.count

Practical Examples

Example 1: User Categorization

name: categorize-user
inputs:
  age:
    type: integer
    description: User's age

actions:
  - kind: SetVariable
    variable: Local.age
    value: =Workflow.Inputs.age

  - kind: SetVariable
    variable: Local.category
    value: =If(Local.age < 13, "child", If(Local.age < 20, "teenager", If(Local.age < 65, "adult", "senior")))

  - kind: SendActivity
    activity:
      text: =Concat("You are categorized as: ", Local.category)

  - kind: SetVariable
    variable: Workflow.Outputs.category
    value: =Local.category

Example 2: Conditional Greeting

name: smart-greeting
inputs:
  name:
    type: string
    description: User's name (optional)
  timeOfDay:
    type: string
    description: morning, afternoon, or evening

actions:
  # Set the greeting based on time of day
  - kind: SetVariable
    variable: Local.timeGreeting
    value: =If(Workflow.Inputs.timeOfDay = "morning", "Good morning", If(Workflow.Inputs.timeOfDay = "afternoon", "Good afternoon", "Good evening"))

  # Handle optional name
  - kind: SetVariable
    variable: Local.userName
    value: =If(IsBlank(Workflow.Inputs.name), "friend", Workflow.Inputs.name)

  # Build the full greeting
  - kind: SetVariable
    variable: Local.fullGreeting
    value: =Concat(Local.timeGreeting, ", ", Local.userName, "!")

  - kind: SendActivity
    activity:
      text: =Local.fullGreeting

Example 3: Input Validation

name: validate-order
inputs:
  quantity:
    type: integer
    description: Number of items to order
  email:
    type: string
    description: Customer email

actions:
  # Check if inputs are valid
  - kind: SetVariable
    variable: Local.isValidQuantity
    value: =And(Workflow.Inputs.quantity > 0, Workflow.Inputs.quantity <= 100)

  - kind: SetVariable
    variable: Local.hasEmail
    value: =Not(IsBlank(Workflow.Inputs.email))

  - kind: SetVariable
    variable: Local.isValid
    value: =And(Local.isValidQuantity, Local.hasEmail)

  - kind: If
    condition: =Local.isValid
    then:
      - kind: SendActivity
        activity:
          text: "Order validated successfully!"
    else:
      - kind: SendActivity
        activity:
          text: =If(Not(Local.isValidQuantity), "Invalid quantity (must be 1-100)", "Email is required")

Next Steps