Free cookie consent management tool by TermsFeed

Create a Custom Chat Interface

On This Page

Tip:  Interface patterns give you an opportunity to explore different interface designs. Be sure to check out How to Adapt a Pattern for Your Application.

Goal

Build a custom chat interface by using the cardLayout component to give each message a distinct visual style.

This design pattern is not recommended for offline interfaces because reflecting immediate changes in an interface based on user interaction requires a connection to the server.

A common approach is to store each message as an object with a sender and text field. Then, apply conditional formatting to display different icons and styles depending on the sender.

Create this pattern

In this pattern, you store each message as an object with a sender and text field. Then, you apply conditional formatting to display different icons and styles depending on whether the sender is the "User" or the "AI". The a!callLanguageModel function is used to generate a response from the AI.

To create this pattern, follow these steps:

  1. Set up local variables.
    • Create local!messages to store the list of chat messages. Initialize it with a "Welcome" message from the "AI" sender.
    • Create local!newMessage to store the user's input from the text field.
  2. Display the message history.
    • Use a!forEach to iterate over the local!messages variable.
    • For each message, display an a!cardLayout. This will put each message in its own visual container.
  3. Apply conditional styling to each message.
    • Inside the iteration, use an a!sideBySideLayout to place an icon next to the message text.
    • Use an if() statement to check fv!item.sender:
      • If sender is "User", show the User icon and set the a!cardLayout style to STANDARD.
      • If sender is "AI", show the Support icon and set the a!cardLayout style to ACCENT.
  4. Create the user input area.
    • Below the a!forEach loop, add an a!sideBySideLayout.
    • In the first item, add a text field that saves its value into local!newMessage.
    • In the second item, add an a!buttonWidget with a "send" icon.
  5. Configure the send button logic.
    • In the button's saveInto parameter, chain multiple a!save functions to execute in order:
      1. Append the user's message (from local!newMessage) to local!messages.
      2. Call a!callLanguageModel with local!newMessage as the prompt. Append the AI's response to local!messages.
      3. Clear the text field by saving null into local!newMessage.

Example expression

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
a!localVariables(
  local!messages: {},
  local!newMessage,
  local!updatedMessages,
  a!sectionLayout(
    label: "Customer Support",
    contents: {

      /* Render messages as cards with alternating margins */
      a!forEach(
        items: local!messages,
        expression: a!cardLayout(
          contents: a!sideBySideLayout(
            items: {
              a!sideBySideItem(
                item: a!richTextDisplayField(
                  value: a!richTextIcon(
                    icon: if(
                      fv!item.sender = "User",
                      "user",
                      "support"
                    )
                  )
                ),
                width: "MINIMIZE"
              ),
              a!sideBySideItem(
                item: a!richTextDisplayField(
                  value: fv!item.text
                )
              )
            }
          ),
          style: if(
            fv!item.sender = "User",
            "STANDARD",
            "ACCENT"
          ),
          marginBelow: if(
            fv!item.sender = "User",
            "LESS",
            "MORE"
          )
        )
      ),

      /* Spacer to add breathing room before the input bar */
      a!richTextDisplayField(
        value: "",
        marginBelow: "STANDARD"
      ),

      /* Input area: text field + send button */
      a!sideBySideLayout(
        items: {
          a!sideBySideItem(
            item: a!textField(
              placeholder: "Describe your issue...",
              value: local!newMessage,
              saveInto: local!newMessage
            ),
            width: "10X"
          ),
          a!sideBySideItem(
            item: a!buttonLayout(
              primaryButtons: {
                a!buttonWidget(
                  icon: "send",
                  style: "LINK",
                  size: "SMALL",
                  saveInto: {
                    /* Append the user's message to create updated history */
                    a!save(
                      local!updatedMessages,
                      append(
                        local!messages,
                        { sender: "User", text: local!newMessage }
                      )
                    ),

                    /* Save the updated messages to display */
                    a!save(local!messages, local!updatedMessages),

                    /* Call Appian's default model and append its reply */
                    a!save(
                      local!messages,
                      append(
                        local!messages,
                        {
                          sender: "AI",
                          text: a!callLanguageModel(
                            prompt: "You are a helpful customer support assistant.",
                            messages: a!forEach(
                              items: local!updatedMessages,
                              expression: {
                                messageContent: fv!item.text,
                                role: if(fv!item.sender = "User", "USER", "ASSISTANT")
                              }
                            )
                          )
                        }
                      )
                    ),

                    /* Clear input */
                    a!save(local!newMessage, null)
                  },
                  disabled: or(isnull(local!newMessage), trim(local!newMessage) = ""),
                  submit: false
                )
              }
            ),
            width: "MINIMIZE"
          )
        }
      )
    }
  )
)

Displays the following:

Scroll or drag to pan · ⌘+/⌘− to zoom · Esc to closeimages/automation/ai-customer-support-ex.png

Test it out

To test this pattern:

  1. Copy and paste the example expression into an interface object.
  2. Observe the interface in Preview mode. You will see the initial "Welcome" message from the AI.
  3. In the text field at the bottom, type a question, such as "How do I reset my password?".
  4. Click the send icon.
  5. Verify that your message appears in the chat history with the user icon and a "STANDARD" style card.
  6. After a moment, verify that a new response from the AI appears below your message, using the support icon and an "ACCENT" style card.

Feedback