Alloy provides everything needed to build powerful chat Actions. Such Actions provide communication with some chat service like ChatGPT service utilizing familiar chat interface. So you can ask questions, get answers, observe an entire conversation, utilize conversation for immediate use or save it for any future needs, save conversations and continue them at a later time etc. 


You may build straightforward actions for dedicated chat services like ChatGPT or you may provide chat interfaces for generic non-chat services. For example the bundled "Image Chat" action provides unified chat interface for three different OpenAI image services: generation, variations and edit services.


The following video demonstrates using the "ChatGPT" action.




Usually a chat Action consists of the Main Workflow having at least a "Chat" task and several utility Workflows responsible for messages sending, conversations refresh and processing of custom commands.

The "Chat" task shows familiar chat user interface that can be used to design and implement chat conversations with chat and messaging services. The task utilizes three workflows to support its core functionality:

  • Send Workflow - this workflow is responsible for sending user's messages and for optionally getting replies. This workflow is called when the user types a message and taps the Send button.
  • Refresh Workflow - this optional workflow is responsible for refreshing the chat conversation by downloading new messages. This workflow is called automatically on the schedule.
  • Command Workflow - this optional workflow is responsible for processing of custom commands. This workflow is called when the user chooses a command either from the "+", "..." or context menus.
  • Function Workflow - this kind of workflows is responsible for processing function calls. There is a particular workflow per each particular function identified by function name.


Those Workflows will be called in background so the UI will be available while they are performing. Only one Workflow can be performed at a time so if there several transactions (like several messages to send) they will be queued.



Send Workflow

This Workflow is responsible for sending user's messages and for optionally getting replies. It is called when:

  • The user designs a message and taps the Send button.
  • The Command Workflow produces new messages to send.


The Send Workflow takes the conversation::ChatConversation input argument with a copy of entire chat conversation; the last chat message in the conversation contains a chat message to send. 


The Send Workflow can optionally obtain some replies to the sent message. To return them it must modify passed chat conversation and return it back via Workflow's  the conversation::ChatConversation output argument. 


A "Set Variables" task can be used to compose replies and add them to the chat conversation. For example:

  1. chatMessage = s:objectFactory.newChatMessage - creates a new chat message
  2. chatMessage.contact = "Kate Bell<kate.bell@apple.com>" - specifies a contact the message came from.
  3. chatMessage.message = REPLY: $(conversation.messages.@lastObject.message) - composes a message as a reply to the sent message.
  4. +conversation.messages = chatMessage - adds a reply to the chat conversation.


Refresh Workflow

This optional Workflow is responsible for refreshing the chat conversation by downloading new messages. This Workflow is called automatically on the schedule controlled by the "Refresh Interval" property.


The Refresh Workflow takes the conversation::ChatConversation input argument with a copy of entire chat conversation. 

To return downloaded new messages it must modify passed chat conversation and return it back via Workflow's  the conversation::ChatConversation output argument. 

A "Set Variables" task can be used to compose downloaded new messages and add them to the chat conversation. For example, to simulate time chat bot:

  1. chatMessage = s:objectFactory.newChatMessage - creates a new chat message
  2. chatMessage.contact = "Time Chat Bot" - specifies a contact the message came from.
  3. chatMessage.message = $(s:dateTime) - composes a message as a current time.
  4. +conversation.messages = chatMessage - adds a reply to the chat conversation.


Custom Commands

It is possible to extend the "Chat" task functionality by specifying custom commands. Those commands will appear in the "+", "..." or context menus and the Command Workflow will be used to handle invoked commands.


You can specify commands as the "Command Workflow | Command List" property. 

Each command has the following format:


prefixCommand<commandID>


Single character prefix identifies type of a command. It can be one of:

  •     specifies a chat command that goes "as is" to the message composer. Such commands will be shown when the user types the  /  in the message composer. Note: the Command Workflow will NOT be called to handle such commands.
  •  +   specifies a new message command that goes to the "+" menu. Such commands should create new messages. For example the +Send Location<sendLocation> command would create a new message with current location.
  •  *    specifies a conversation command that goes the "..." menu. Such command should do something with entire conversation. For example, the *Share<share> command would share the conversation.
  • ^  specifies a context menu command. Such commands will be shown in the context menu invoked for a message and are intended to perform some actions with a single message.


Command provides the name of a command and identifies it if no commandID is specified. The name will be shown in all the menus and lists.


Optional commandID provides immutable ID of a command. If it is specified it will be passed the the Command Workflow; otherwise Command will be passed instead. In any cases the prefix will be stripped. Note: it is better to always specify commandID so if you decide to change command name all the tasks that rely on a specific command will be held intact.


There are two predefined context menu commands that are always available and should not be listed explicitly:

  • messageTap - fired when the user taps a message

  • messageDoubleTap - fired when the user double taps a message


For example, the following task handles both the preview and messageTap commands by showing image preview for chosen message:


Command Workflow

This optional Workflow is responsible for processing of custom commands. This workflow is called when the user chooses a command either from the "+", "..." or context menus. 


The Command Workflow takes:

  •  conversation::ChatConversation input argument with either  copy of entire chat conversation for most of the commands or a conversation with just one selected message for context menu commands.
  • command::String input argument with a command.  

To return messages it must modify passed chat conversation and return it back via Workflow's  the conversation::ChatConversation output argument. 

Chat Functions

Chat "functions" represent activities should be done in response to some incoming messages. Such incoming messages can either:

  • contain clear instructions which "function" should be called together with its arguments or
  • the "function" and its arguments can be determined based on the message content


Example of such functions can be: getting weather forecast, sending emails, getting some statistics data, finding contacts etc.




To initiate a function call the "Send" or "Refresh" workflows should simply add a new "Chat Message" with the "Function" Type, function name as the Message, and function arguments as the "Custom Data". As result a Workflow having exact name of the function will be automatically called  with the conversation::ChatConversation and arguments::Map arguments.



A "function" Workflow after performing desired activities may:

  • Indicate that "function" was completed (e.g. by posting a local notification) and do not update the Chat Conversation
  • Add some "incoming" messages to the Chat Conversation with the results of the "function"
  • Return the results of the "function" to the sender for further processing by automatic sending results via the "Send" workflow. This can be done simply by adding a new "Chat Message" with the "Function Result"Type, function name as the Message, and function result as the "Custom Data".


A "function" Workflow  has the following arguments:

  1. conversation::ChatConversation - a Chat Conversation to work with
  2. arguments::Map - arguments for a function call


A "function" Workflow  should return a conversation::ChatConversation. Usually it just returns the same conversation as passed to the Workflow.

Draft Messages Support

The "Chat" task supports draft messages. Any messages created by Workflows can be marked as draft ones so they will not be sent automatically but rather will go to the message composer. Such draft messages will be shown above the text entry field and it is possible to remove any of them. This allows to check those messages before sending to avoid any privacy issues. 


To mark any message as draft one its draft property should be set to 1 using a "Set Variables" task:


chatMesage.draft = 1


Maintaining the History of Conversations

The "Chat" task can automatically maintain the history of all conversations. To turn it ON the history property of a "Chat" task should be specified. If the history is enabled - it is possible to switch to any past conversations, save altered conversations etc.


 If current conversation is altered the user will be prompted to save it or discard changes when switching to other conversation or cancelling the "Chat" task. Also it is possible to save a copy of current conversation by long tap on the Done button and choosing the "Commit Copy" action.


The "Chat Sample" Task

You may explore the "Chat Sample" task to learn how to make a chat action. This action:

  • Simulates sending and getting replies by  by posting "REPLY:" prefixed messages. 
  • Simulates refreshing and getting new messages by posting current time.
  • Showcases adding custom commands to send locations and contacts
  • Showcases adding custom commands to share and edit entire conversation




The Refresh Workflow takes the conversation::ChatConversation input argument with a copy of entire chat conversation. 

To return downloaded new messages it must modify passed chat conversation and return it back via Workflow's  the conversation::ChatConversation output argument. 

A "Set Variables" task can be used to compose downloaded new messages and add them to the chat conversation. For example, to simulate time chat bot:

  1. chatMessage = s:objectFactory.newChatMessage - creates a new chat message
  2. chatMessage.contact = "Time Chat Bot" - specifies a contact the message came from.
  3. chatMessage.message = $(s:dateTime) - composes a message as a current time.
  4. +conversation.messages = chatMessage - adds a reply to the chat conversation.


Command Workflow

This optional Workflow is responsible for processing of custom commands. This workflow is called when the user chooses a command either from the "+" or "..." menus. You can specify commands as the "Command Workflow | Command List" property. 

Each command has the following format:


prefixCommand<commandID>


Single character prefix identifies type of a command. It can be one of:

  •  /    specifies a chat command that goes "as is" to the message composer. Such commands will be shown when the user types the   in the message composer.
  •  +   specifies a new message command that goes to the "+" menu. Such commands should create new messages. For example the +Send Location<sendLocation> command creates a new message with current location.
  •  *    specifies a conversation command that goes the "..." menu. Such command should do something with entire conversation. For example, the *Share<share> command shares the conversation.


Command provides the name of a command and identifies it if no commandID is specified. The name will be shown in all the menus and lists.


Optional commandID provides immutable ID of a command. If it is specified it will be passed the the Command Workflow; otherwise Command will be passed instead. In any cases the prefix will be stripped. Note: it is better to always specify commandID so if you decide to change command name all the tasks that rely on a specific command will be held intact.


You may explore the "Chat Sample" task to learn how to make a chat action. This action:

  • Simulates sending and getting replies by  by posting "REPLY:" prefixed messages. 
  • Simulates refreshing and getting new messages by posting current time.
  • Showcases adding custom commands to send locations and contacts
  • Showcases adding custom commands to share and edit entire conversation