# App Builder

## Core Concepts of App Builder

The core concept behind the App is a state machine integrated with tasks that can perform AI functions, transitioning between different states through user interactions.

App Builder has significant differences from Workflow:

1. **Essence**: Workflow executes each node sequentially until a one-time completion, while the App can interact with users indefinitely without stopping, and developer can have full agency on setting the user journey.
2. **Editing Interface**: In Workflow, the connections between nodes represent data transmission; in the App, connections between widgets represent user interactions. The content of Workflow nodes is embeded within the nodes, while in the App, most of the widget content sourced from external forms.

<figure><img src="/files/Pj9NAhtv9OPTk7wFuJcq" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/8yCFJHiUmILISNRPgFQk" alt=""><figcaption><p><em>The above image is Workflow, the below image is App Builder</em></p></figcaption></figure>

### App State Machine

Taking a chat agent as an example, generally speaking, in the App, a State corresponds to a reply message from the bot. Users can transition to different State through various actions such as text input, voice input,clicking buttons, or filling forms.

Each State of the agent can run different AI modules (Tasks) based on the input, or collectively build the reply content (Message). It can also output some other results (Outputs) for use by other States.

## App Builder

The App Builder is a no-code canvas-like editor where you set up States and connect Widgets to build your App.<br>

<figure><img src="/files/cOX7eH3GB7vubnhIU8Oc" alt=""><figcaption></figcaption></figure>

The left side includes two types of interactive entities:

* **State**: Corresponds to a State in Pro Config editing mode, which can be dragged onto the canvas.
* **Widget**: Corresponds to AnyWidgetModule in Pro Config editing mode, which can be dragged under a State's Task or added by clicking "Add" under Task. Currently, only the following two Widgets are supported, and we will soon support many more widgets in future updates:
  * **Workflow Runner Widget**: This Widget can execute a specified Workflow
  * **GPT Widget**: This Widget can call a specified GPT model

## Start Node

You can set the Context; Variables under Context can be accessed by all States and can be modified by any State.

For how to access them, please refer to [#using-variables](#using-variables "mention") in this chapter, and for how to modify them, please refer to [#modifying-context-variables](#modifying-context-variables "mention") in this chapter.

{% hint style="info" %}
**For developers who are familiar with Pro Config mode**: The Start state corresponds to Automata in ProConfig. However, Automata can set global transitions, which the current App Builder does not support.
{% endhint %}

## State

### Input

State Input has the same functionality as the Input of the Workflow Start node; it represents the parameters accepted by the current State.

Just like in Workflow, an Input includes a name, type, and more advanced settings.

<figure><img src="/files/NOLSks0XgmRPXB1icgdc" alt="" width="375"><figcaption></figcaption></figure>

Compared to Workflow, it is more complex because Inputs have more sources:

**User Input (User Input: True)**: This input is filled in by user.

<figure><img src="/files/8Ddk09F1rRAP5YR3biAV" alt="" width="375"><figcaption></figcaption></figure>

* **Form Input (Source: form)**: User fills in the input in a form that pops up when clicking a button. &#x20;

<figure><img src="/files/2k2XpQ60mmjAHFsmnYmQ" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/HjQlg025imucZAX5ODjS" alt="" width="375"><figcaption></figcaption></figure>

* **Chat Input (Source: IM)**: User inputs in the chat input box. &#x20;

<figure><img src="/files/xk7ktSx5jXOsUqNbkg6Z" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/9ZcgHt6pnzwANolpPZOX" alt="" width="375"><figcaption></figcaption></figure>

**Non-user Input (User Input: False)**: This input is set by the developer.

* **Transferred Input**: Other States assign values to this Input when transitioning to this State.
* **Local Variables**: Variables that will be used by this State.

{% hint style="info" %}
To avoid unnecessary issues, we recommend that the User Inputs in a single State be either all form inputs or all IM inputs.
{% endhint %}

{% hint style="info" %}
The State connected to the Start node is the initial state; the Input of the initial state will be ignored during the first run. You can create a greeting statement that does not require Input as the initial state, or set default values for Inputs to avoid errors caused by missing values.
{% endhint %}

### Task

A Task is a call to a Widget.

After adding a Task, click its name to edit the corresponding configuration and see its returned data structure.

<figure><img src="/files/hfZHMUijLg9au8p6xXpi" alt="" width="375"><figcaption></figcaption></figure>

You can use the Task's name to reference its returned results.

<figure><img src="/files/EWOdMzosa1EzhoYWPikL" alt="" width="366"><figcaption></figcaption></figure>

{% hint style="info" %}
Tasks are executed sequentially; each Task can only reference the results of previously executed Tasks.
{% endhint %}

### Output

Output is mainly used to output variables for other States to use. Whenever certain data can be repeatedly used , such as Task execution results or user Inputs, you can set them as Outputs.

Outputs can be created as new Output variables or by modifying existing Context variables.

#### Creating a New Output Variable

* Create a new Output variable

<figure><img src="/files/FyaN6KW8tu0MKhAVU8gP" alt="" width="365"><figcaption></figcaption></figure>

* Edit its properties

<figure><img src="/files/xRoqFP1qjM7ZHvRlLU2F" alt="" width="353"><figcaption></figcaption></figure>

* Modify the Variable Name and other properties, then confirm.

<figure><img src="/files/G7vWPzdpb76K50shq4SE" alt="" width="375"><figcaption></figcaption></figure>

* Assign a value to the Output variable. The assignment method is the same as [#using-variables](#using-variables "mention").

<figure><img src="/files/UTr4V58QCa7zXE9XHFfM" alt="" width="375"><figcaption></figcaption></figure>

After creation, this Output can be referenced in other States.

<figure><img src="/files/FjdkevWm9VWqRWjFDEVP" alt="" width="372"><figcaption></figcaption></figure>

{% hint style="info" %}
Note that any State can reference the Outputs of any other State, but there is no guarantee that the referenced State can be executed. Therefore, be mindful of the execution order of States when referencing.
{% endhint %}

#### Modifying Context Variables

* Create a new Output variable

<figure><img src="/files/XYWb75tRzHlYHuQsuZl3" alt="" width="365"><figcaption></figcaption></figure>

* Edit its properties

<figure><img src="/files/rPuVodQcjz9SqavmwSnO" alt="" width="353"><figcaption></figcaption></figure>

* Set Variable Name mode to Select Output

<figure><img src="/files/4fBnvrH0KeAkg62rZZvh" alt="" width="375"><figcaption></figcaption></figure>

* Select the Context variable you want to modify and confirm

<figure><img src="/files/r8SqTV8gcvHqagJAlmtV" alt="" width="375"><figcaption></figcaption></figure>

* Assign a new value to the Context variable. The assignment method is the same as [#using-variables](#using-variables "mention")

<figure><img src="/files/j7bEzEcxI81hC1k5qeQz" alt="" width="375"><figcaption></figcaption></figure>

### Message

Control what content the chat agent replies to the user, which can include text, images, audio, and buttons.

* **Text** supports using expressions to reference variables, Markdown syntax, and a few HTML elements (`<img>`, `<audio>`, `<video>`, `<a>`, and you can set width and height for them).
* **Images** support using a single image or an array of images.
* **Audio** supports a single audio file.
* **Buttons** can create as many as you want; when users are interacting with the App, users can click buttons to transition to other States or rerun the current State.

Buttons are relatively more complex; their configuration includes Button Name, Button Prompt, and Payload fields. After configuration, you can connect the button on the canvas to the State it needs to transition to when clicked (it can be the same State). Advanced configurations for transitions can be made, which will be introduced in the next section on Transition.

<figure><img src="/files/NAFApmE8dmyfPhwOsGXo" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/rkDZoXLhuUIPVzXVXN44" alt="" width="375"><figcaption></figcaption></figure>

**Payload** can create some variables when the user clicks. It generally has two use cases:

* **Perceiving User Actions**: For example, two buttons (Style 1, Style 2) correspond to the same variable (`style`) but with different data (1, 2). This way, clicking different buttons can transition to the same State but with different input data.

<figure><img src="/files/lHHP7dGBT0wglsyGKD3t" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/6CDR1oI7qnNMpbXxJ56j" alt="" width="375"><figcaption></figcaption></figure>

* **Making Data Snapshots in Chat History**: Since each specific button creates and records the Payload when displayed, clicking buttons in the chat history can retrieve historical snapshot data.

## Transition

In the App Builder, transitions are represented by connections on the canvas. The right side represents outputs, and the left side represents inputs.

There are three types of transitions on the canvas, representing different trigger conditions:

* **CHAT**: Transition triggered after the user inputs content in the chat input box, achieved by connecting the circle on the right side of the simulated chat input box below the State node to another State.&#x20;

<figure><img src="/files/Hg6TVjF4twi2AzWckCdF" alt=""><figcaption></figcaption></figure>

* **ALWAYS**: Transition directly to another State after the State execution is complete, achieved by connecting State to State.&#x20;

<figure><img src="/files/p46YqHzz1zyUJ8y6zg8I" alt=""><figcaption></figcaption></figure>

* **Custom Click Events**: Triggered when the user clicks a button, achieved by connecting the circle on the right side of the button to another State.&#x20;

<figure><img src="/files/ZRkcKvZSVT0v9gaTlpSA" alt=""><figcaption></figcaption></figure>

### Editing Transition

Click the small square button at the midpoint of the connection line; a Transition editing form will pop up on the right. You can add conditional transitions and set target inputs.

<figure><img src="/files/1ATboyM1b5lTsd4s3hyo" alt=""><figcaption></figcaption></figure>

#### Conditional Transition

Transitions can conditionally jump to different States. A set of Conditions and Target State settings is called a Transition Case. For example, in the figure below, you can transition to the **winner** state or **continue** state based on whether the user's current score is greater than 10.

<figure><img src="/files/ojWSDnrxFG10rHaNyM2N" alt="" width="375"><figcaption></figcaption></figure>

Enter logical expressions in the **Condition** (refer to [#expressions](#expressions "mention")) for judgment; the result of the expression should be `True` or `False`. During execution, Transition Cases are evaluated in order (from top to bottom in the interface); the first Transition Case whose Condition evaluates to `True` will take effect, and subsequent Transition Cases will not be evaluated.

If the Condition is left blank, it is equivalent to setting it as default `True`.

#### Target Inputs

When transitioning to the Target State, you can also assign values to its Inputs. This is similar to a function calling in programming and passing parameters during the call.

## Using Variables

For many fields, we support three modes of assignment:

* **UI Mode**: Directly edit in the form.&#x20;

<figure><img src="/files/8chKhLdcuSMjXCnXwCDm" alt="" width="361"><figcaption></figcaption></figure>

* **Ref Mode**: Reference other variables.&#x20;

<figure><img src="/files/XqixwNqYUbvh3m0hTGVq" alt="" width="367"><figcaption></figcaption></figure>

* **Code Mode**: Use programming language expressions to combine other variables or perform simple data processing through code.&#x20;

<figure><img src="/files/YZ5qU4lLz0WxWLy5HLcO" alt="" width="365"><figcaption></figcaption></figure>

You can usually switch modes by clicking on the right side or upper right corner of the field form item.

### Expressions

We support expressions, which is often a very powerful way of making state machine more controllable, and making it convenient for developers to perform simple calculations on variables.

In modes that support expressions, expressions are enclosed within double curly braces `{{ }}`. Variables can be referenced using `/`.

Common use cases for expressions include:

1. Concatenating text.
2. Accessing part of complex data, such as getting the first item of an array.
3. Calculating Conditions in Transitions.

For more complex calculation scenarios, we will later support a Code Runner Widget to execute functions.

> \[!TIP] We currently support expressions in the Python language. JavaScript expressions will be supported later. Python expressions currently support the following libraries:
>
> * builtins
> * marshal
> * math
> * time

## Using GPT widget

You need to click **Settings** to set the environment variable `OPENAI_API_KEY`.

{% hint style="info" %}
To use GPT models, currently you need to have your own OpenAI API Key. Due to the fact that ShellAgent is an open-sourced project, MyShell cannot provide limitless free API keys to everyone. However, we will connect the MyShell account's battery system with ShellAgent in the future, so that developers can use the batteries in their MyShell account to build with ShellAgent.&#x20;
{% endhint %}

{% hint style="info" %}
This API Key will only be used for building purposes in your local open-sourced project. Once you export the bot's JSON file from ShellAgent to MyShell's website, all API compute costs will still be hosted by MyShell.
{% endhint %}

<figure><img src="/files/vjLcwVi3kLNUNH0LJEuD" alt="" width="365"><figcaption></figcaption></figure>

## FAQ

### How to Format Bot Messages

You can use Markdown in **Message.Text**.

If you need multimedia elements, you can add corresponding HTML elements. For example:

<figure><img src="/files/Epkn4nlmLqmCXnVJ89MF" alt="" width="367"><figcaption></figcaption></figure>

### How to Set Image Size in Bot Messages

Turn off the **Message.Image** switch, insert `<img />` in **Message.Text**, and set its width and height. For example:

<figure><img src="/files/IfXhdjesVe90eUwsnWF0" alt="" width="375"><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.myshell.ai/create/shellagent-mode/app-builder.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
