Docs: add execution-modes.md (RUNTIME vs WORKFLOW), update HEAR and script-execution-flow

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-03-16 23:28:12 -03:00
parent ae09de3dea
commit 94ca51a670
4 changed files with 130 additions and 0 deletions

View file

@ -0,0 +1,116 @@
# BASIC Execution Modes: RUNTIME vs WORKFLOW
General Bots BASIC scripts run in one of two execution modes. The mode is selected by a pragma at the top of the `.bas` file.
## Quick Comparison
| Feature | RUNTIME mode (default) | WORKFLOW mode ⚗️ |
|---------|----------------------|-----------------|
| **Pragma** | _(none)_ | `#workflow` |
| **Engine** | Rhai AST | Step engine + PostgreSQL |
| **HEAR behavior** | Blocks a thread | Suspends to DB, zero threads |
| **Server restart** | Loses position | Resumes exact step |
| **Side-effect re-run** | ❌ possible on crash | ✅ never |
| **Multi-day flows** | ❌ (1h timeout) | ✅ unlimited |
| **FOR EACH loops** | ✅ | ❌ |
| **FUNCTION / SUB** | ✅ | ❌ |
| **USE WEBSITE** | ✅ | ❌ |
| **Startup time** | ~1ms | ~2ms |
| **RAM per session** | 1 thread (~64KB) | 0 threads |
| **Observability** | Logs only | DB rows (queryable) |
| **Best for** | Tools, short dialogs | Multi-step dialogs, tickets, approvals |
---
## RUNTIME Mode (default)
Every `.bas` file without `#workflow` runs in RUNTIME mode. The script compiles to a Rhai AST and executes in a `spawn_blocking` thread. `HEAR` blocks the thread until the user replies (up to `hear-timeout-secs`, default 3600).
```basic
' ticket.bas — RUNTIME mode (no pragma)
TALK "Describe the issue"
HEAR description ' blocks thread, waits
SET ticket = CREATE(description)
TALK "Ticket #{ticket} created"
```
**When to use:** Tool scripts called by LLM, short dialogs (< 10 minutes), scripts using `FOR EACH`, `FUNCTION`, or `USE WEBSITE`.
---
## WORKFLOW Mode ⚗️
> **Status: Planned feature** — see `botserver/WORKFLOW_PLAN.md`
Add `#workflow` as the first line. The compiler produces a `Vec<Step>` instead of a Rhai AST. Each step is persisted to `workflow_executions` in PostgreSQL before execution. On `HEAR`, the engine saves state and returns — no thread held. On the next user message, execution resumes from the exact step.
```basic
#workflow
' ticket.bas — WORKFLOW mode
TALK "Describe the issue"
HEAR description ' saves state, returns, zero threads
SET ticket = CREATE(description)
TALK "Ticket #{ticket} created"
```
**When to use:** Multi-step dialogs, ticket creation, approval flows, anything that may span minutes or days.
### Keyword compatibility in WORKFLOW mode
| Category | Keywords | WORKFLOW support |
|----------|----------|-----------------|
| **Dialog** | `TALK`, `HEAR`, `WAIT` | ✅ |
| **Data** | `SET`, `GET`, `FIND`, `SAVE`, `INSERT`, `UPDATE`, `DELETE` | ✅ |
| **Communication** | `SEND MAIL`, `SEND TEMPLATE`, `SMS` | ✅ |
| **AI** | `USE KB`, `USE TOOL`, `REMEMBER`, `THINK KB` | ✅ |
| **HTTP** | `GET` (http), `POST`, `PUT`, `PATCH`, `DELETE` (http) | ✅ |
| **Scheduling** | `SCHEDULE`, `BOOK`, `CREATE TASK` | ✅ |
| **Expressions** | `FORMAT`, math, datetime, string functions | ✅ (via Rhai eval) |
| **Control flow** | `IF/ELSE/END IF` | ✅ |
| **Loops** | `FOR EACH / NEXT` | ❌ use RUNTIME |
| **Procedures** | `FUNCTION`, `SUB`, `CALL` | ❌ use RUNTIME |
| **Browser** | `USE WEBSITE` | ❌ use RUNTIME |
| **Events** | `ON EMAIL`, `ON CHANGE`, `WEBHOOK` | ❌ use RUNTIME |
### How WORKFLOW compiles
The compiler does **not** use Rhai for workflow mode. It is a line-by-line parser:
```
TALK "Hello ${name}" → Step::Talk { template: "Hello ${name}" }
HEAR description → Step::Hear { var: "description", type: "any" }
SET x = score + 1 → Step::Set { var: "x", expr: "score + 1" }
IF score > 10 THEN → Step::If { cond: "score > 10", then_steps, else_steps }
SEND MAIL to, s, body → Step::SendMail { to, subject, body }
```
Expressions (`score + 1`, `score > 10`) are stored as strings and evaluated at runtime using Rhai as a pure expression calculator — no custom syntax, no side effects.
### Observability
In WORKFLOW mode, every step is a DB row. You can query execution state directly:
```sql
SELECT script_path, current_step, state_json, status, updated_at
FROM workflow_executions
WHERE session_id = '<session-uuid>'
ORDER BY updated_at DESC;
```
---
## Choosing a Mode
```
Does the script use FOR EACH, FUNCTION, or USE WEBSITE?
YES → RUNTIME (no pragma)
Does the script have HEAR and may run for > 1 hour?
YES → WORKFLOW (#workflow)
Is it a tool script called by LLM (short, no HEAR)?
YES → RUNTIME (no pragma)
Is it a multi-step dialog (ticket, approval, enrollment)?
YES → WORKFLOW (#workflow) ⚗️ when available
```

View file

@ -2,6 +2,17 @@
The `HEAR` keyword pauses script execution and waits for user input. With optional type validation, it automatically verifies and normalizes input, retrying with helpful error messages when validation fails.
## Execution behavior by mode
| Mode | HEAR behavior | Thread held | Crash-safe |
|------|--------------|-------------|------------|
| **RUNTIME** (default) | Blocks `spawn_blocking` thread | Yes (up to `hear-timeout-secs`) | No |
| **WORKFLOW** ⚗️ | Saves state to DB, returns immediately | No | Yes |
In RUNTIME mode, the script thread is suspended — not re-run from the top. All code above `HEAR` does **not** execute again when the user replies. The timeout is configurable via `hear-timeout-secs` in `config.csv` (default: 3600 seconds).
In WORKFLOW mode (`#workflow` pragma), `HEAR` persists the current step and all variables to PostgreSQL and returns. The thread is released. When the user replies, execution resumes from the exact `HEAR` line. See [Execution Modes](./execution-modes.md).
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Basic Syntax

View file

@ -2,6 +2,8 @@
Understanding how General Bots BASIC scripts are loaded, compiled, and executed is essential for building effective automation. This document covers the complete execution lifecycle.
> **Two execution modes exist:** RUNTIME (default) and WORKFLOW. See [Execution Modes](./execution-modes.md) for the full comparison.
## Execution Entry Points
Scripts in General Bots can be triggered through several entry points:

View file

@ -73,6 +73,7 @@
- [Chapter 4: BASIC Scripting](./04-basic-scripting/README.md)
- [BASIC Basics](./04-basic-scripting/basics.md)
- [Execution Modes: RUNTIME vs WORKFLOW](./04-basic-scripting/execution-modes.md)
- [API Possibilities](./04-basic-scripting/api-possibilities.md)
- [Universal Messaging](./04-basic-scripting/universal-messaging.md)
- [BASIC vs n8n/Zapier/Make](./04-basic-scripting/basic-vs-automation-tools.md)