Skip to content

General Chain Architecture

A MyCode.Bot scenario is built as a chain of nodes. Each node has its own role in the scenario: starts execution, shows a message, waits for input, calls an API, checks a condition, stores data, or finishes execution.

A node starts working when execution reaches its input. After it finishes, it either passes control to the next node, shows a screen and waits for a new user action, or ends the scenario.

How to Read a Schema

Concept Meaning
Input A connection that brings execution into a node. Multiple previous nodes can lead to the same input.
Standard output A NextAction transition to one next node.
Special output A separate branch, such as True / False, Prompt / Invalid, or a specific button output.
Entry point A node that starts a new scenario: Trigger, Agent trigger, Error, or a system event.
Terminal node A node without a next transition. For example, JSON output returns JSON, and Chat transfers the dialog to an operator.

The editor stores connections as action strings. Regular nodes use node:{id}, screens use go_to_screen:{id}, and event/webhook nodes can have a system or custom action. In the panel, connect nodes through connectors instead of entering these service strings manually.

Quick Catalog

Node Technical name Main purpose Outputs Waits for user Typical mode
Event Event Starts a scenario from an event. See Event Types. 1 No Messenger
HTTP webhook Soon HttpWebhook Starts a scenario from an external HTTP POST 1 No Webhook
Screen Screen Shows a message, image, and buttons Buttons + fallback Yes Messenger
Keyboard Screen Screen Shows a screen with keyboard answer options Buttons + fallback Yes Messenger
Carousel screen CarouselScreen Shows a carousel of cards with buttons (Instagram only) Card buttons + fallback Yes Instagram
Share phone screen SharePhoneScreen Asks the user to share a phone number 1 Yes Messenger
Input UserInput Validates and normalizes the entered value Next / Prompt / Invalid As needed Messenger
Viber survey ViberSurvey Shows a survey and branches by answer One per option + fallback Yes Viber Business
HTTP request HttpRequest Calls an external HTTP API 1 No Messenger / AI tool
JSON processor JsonProcessor Converts JSON or text into variables 1 No Messenger / AI tool
Condition Condition Selects a true or false branch with a JS condition 2 No Messenger / AI tool
Switch SwitchNode Routes the scenario by an exact value One per case + default No Messenger
Set user tag SetUserTag Adds a tag to the current member 1 No Messenger
Get user tag GetUserTag Reads the member tags into a variable (JSON array) 1 No Messenger
User has tag UserHasTagNode Checks the member tags and branches 2 (True / False) No Messenger
Remove user tag RemoveUserTagNode Removes one tag of the current member 1 No Messenger
Set memory SetMemory Stores a field set across executions 1 No Messenger
Get memory GetMemory Reads stored fields into variables 1 No Messenger
Chat Soon Chat Transfers the dialog to an operator 0 No Messenger handoff
JSON output JsonOutput Returns the final JSON from an AI tool 0 No AI tool

Processor is visible in GET /api/BotSchema/node-types with code 3, but it is only a reserved enum value. It has no concrete node, DTO/mapper, settings form, CRUD endpoint, or runtime behavior, so it cannot be created and used as a node.

HttpWebhook has a backend creation API and runtime endpoint, but the current backend does not have HttpWebhookNodeMapper. Because of this, the node is not returned in the general schema DTO response and is not fully available in the standard editor UI. It is not currently used on the frontend; until the integration is clarified, it is marked as Soon.

Event Types

Event is the technical node behind several entry points. The quick catalog shows it as Event, but the concrete startup scenario is selected by EventType.

EventType When it is used
OnMemberFollow Initial entry flow for Telegram /start and Viber conversation_started; can also run for an existing member.
OnEnd Reserved end event; no automatic host trigger was found in the checked backend.
OnError Separate error-handling branch. In the builder, it can appear as Error.
OnTrigger Startup by custom action/parameter.
OnChatClosed New scenario after an operator chat is closed.
OnAgentTriggered Entry into a synchronous AI tool; corresponds to Agent trigger in the builder.

How Execution Works

Within one execution, nodes run sequentially: a node receives control on its input, performs its action, and passes control through a standard or special output.

Event -> HTTP request -> Condition -> Screen

If a node shows a screen and waits for a user action, the current execution ends. The next message or button click starts a new execution. The backend carries the current input and system member context into it, but not the whole result dictionary from the previous run.

Because of this, data that must survive several user messages should be stored separately: with Set memory / Get memory or in the user tags.

#var Variables

A variable is stored in context without #, but in templates its key is written with #:

#member.name
#node.12.http.statusCode
#node.25.customerName

Names can contain Latin letters, numbers, _, and dot-separated segments. For example, #node.12.http.statusCode is a valid key, while a key with a hyphen is not read as one variable. Key lookup is case-insensitive, but keeping one writing style improves readability.

In regular text, a missing variable is replaced with an empty string. So Hello, #member.name! becomes Hello, ! if the name is not set.

There is no separate escape syntax for a literal #name: that sequence is treated as a variable and disappears from the result if the key is missing.

System Variables

When a scenario starts with member context, these variables are available:

Variable Meaning
#member.name Member name
#member.phone Member phone
#member.second_name Second name or surname from the member model
#member.nick Member nickname
#member.external_id Member ID in the external messenger
#member.tags Member tags as a JSON array string, for example ["vip","kyiv"]. Updated during the current execution after Set user tag or Remove user tag.
#bot.name Bot name

In a webhook without a matched member, and in an AI tool, member context is absent, so these values are empty or unavailable.

Variables Created by Nodes

Most nodes write their result under #node.{id}.*. For example, if HTTP request has ID 12, the response code is available as #node.12.http.statusCode.

Source Typical key
Input after Screen or Keyboard Screen #node.{screenId}.{TargetKey}
Input #node.{id}.{TargetKey}
Viber survey #node.{id}.{TargetKey}
Event #node.{id}.event_triggered, #node.{id}.trigger_param
HTTP request #node.{id}.http.statusCode, #node.{id}.http.isSuccess, #node.{id}.http.rawBody, #node.{id}.http.reasonPhrase, #node.{id}.http.queued in async mode, and JSON fields
JSON processor JSON fields or #node.{id}.json.source
Condition #node.{id}.condition.result, #node.{id}.condition.action, sometimes #node.{id}.condition.error
User has tag #node.{id}.userHasTag.result
Switch #node.{id}.switch.result, #node.{id}.switch.action
Get user tag #node.{id}.{OutputKey}
Get memory #node.{id}.{memoryField}
JSON output #node.{id}.json.raw before execution ends

The exact list of available values for a node can be taken from the variable picker. Values in that list can be empty: this is a hint about a key, not a promise that runtime already has data.

Variable Lifetime

Regular #var values live only within one chain execution. When the bot shows a Screen and stops, the user's next message starts a new execution.

The backend carries the current input and system member context into the new execution, but not the whole result dictionary from the previous run.

Practical rule:

  • use regular variables between nodes that run without a pause;
  • after Screen, the new input is guaranteed as #node.{screenId}.{TargetKey};
  • to preserve other data across several messages, use Set memory / Get memory or user tags.

Where Substitution Works

Field #var {{ JS }}
Screen: message title/text/photo URL Yes Yes
Share phone screen: message and share-button text Yes Yes
Viber survey: question text Yes Yes
HTTP request: body template Yes Yes
HTTP request: header values Yes Yes
HTTP request: URL Yes Yes
JSON processor: JSON template Yes Yes
JSON output: JSON template Yes Yes
Set memory: value template Yes Yes
Set user tag: tag value No No
Condition: expression Yes Yes, as a boolean expression

Regular Screen buttons, Viber survey answer texts, memory field names, MemoryName, and TargetKey do not pass through the template renderer.

JavaScript in Nodes

In text or JSON templates, JavaScript is written between {{ and }}:

Hello, {{ truncate(#member.name, 20) }}!
{
  "customer": {{ JSON.stringify(#member.name) }},
  "is_success": {{ #node.12.http.isSuccess }}
}

Before execution, #var values are converted into JS values:

  • true / false become booleans;
  • a number in invariant format becomes a number;
  • other text becomes a safe JS string literal;
  • a missing key becomes null.

For JSON, it is better to use JSON.stringify(...) when the value is inserted outside already opened quotes. A simple construction like "name": "#member.name" can create invalid JSON if the value itself contains quotes or special characters.

Conditions

Condition.Expression accepts a raw JS expression or an expression wrapped in one outer {{ ... }} pair:

#node.12.http.statusCode == 200 && #node.12.http.isSuccess
parseJson(#node.12.http.rawBody).items.length > 0

The result is converted to boolean. Empty string, 0, false, no, null, undefined, and NaN mean false. A non-zero number, true, yes, and any other non-empty string mean true. Objects and arrays are not converted directly to boolean - compare a specific property or length.

Available Helper Functions

Function Purpose Example
truncate(value, length) Cuts text and adds ... {{ truncate(#member.name, 10) }}
parseJson(json) Converts a JSON string into a JS object {{ parseJson(#node.12.http.rawBody).order.id }}
parseBase64Json(base64) Decodes base64 JSON and returns an object {{ parseBase64Json(#node.5.payload).status }}

Standard JavaScript expression features, including field access, arrays, .map(...), .join(...), and global JSON, are executed by the Jint engine.

JS Limits and Errors

  • Condition.Expression rejects expressions with ; as disallowed statements. In a regular {{ JS }} template, an expression with ; is not executed and silently produces an empty fragment.
  • One expression has a 100 ms timeout, a maximum of 50 statements, and recursion depth 5.
  • In a regular template, a JS error stops the node. Exception: an undefined identifier produces an empty fragment.
  • In Condition, a missing #var becomes null and usually leads to the false branch without an error.
  • A syntax or runtime error in Condition adds an execution error and stops the scenario. It is not an automatic transition to the false branch.
  • HTML entities inside an expression are decoded, so > saved by the editor is executed as >.

Nodes Available in AI Tool

A synchronous AI tool cannot wait for a new human message or show a messenger screen. The practically supported skeleton is:

Agent trigger -> HTTP request / JSON processor / Condition -> JSON output in every branch
Node In AI tool Reason
Agent trigger Yes Entry point and argument validation
HTTP request Yes Synchronous external API call
JSON processor Yes Synchronous variable formation
Condition Yes Synchronous branching
JSON output Yes Required terminal result
Screen, Keyboard Screen, Carousel screen, Share phone screen, Input, Viber survey No Wait for user interaction
Chat No Terminal handoff without JSON
Set user tag, Get user tag, User has tag, Remove user tag No No member context/post-processing tool flow
Set memory, Get memory No Memory dispatcher requires member UserId
Switch No Not part of the verified AI tool skeleton
HTTP webhook Not recommended External entry point, not a tool processing step
Other Event nodes Not recommended A tool should start through the single Agent trigger
Processor No Reserved enum value without node implementation