SESI PROGRAMMING LANGUAGE DOCS
⌕

Sesi Language Specification

1. Philosophy & Design Principles

Sesi is built on these core principles:

  1. Conciseness and Legibility: The syntax is minimal
  2. Buildable from Scratch: Sesi is a complete, functioning language with its own lexer, parser, and interpreter.
  3. Simplicity Enables Power: Because the core language is simple, complex operations (like hitting APIs or orchestrating processes) become trivial extensions of the language, rather than tangled SDK implementations.
  4. Transparency Over Magic: Sesi executes exactly what you write.
  5. Practicality: Focus on reducing boilerplate code, emphasizing what developers actually need over academic completeness.

2. Target Users

Primary: Developers who want a clean, fast, and legible language where writing code, whether purely logic-based or calling out to a Reasoning model, is completely frictionless.

Secondary:

  • Engineers transitioning from traditional languages (TypeScript, Python, Go)
  • Developers looking for minimal boilerplate.
  • Teams requiring complex logic with a fraction of the boilerplate

Use Cases:

  • Writing clean CLI tools and scripts
  • Interacting with APIs without SDK boilerplate
  • Quickly orchestrating shell commands
  • Rapid prototyping and scripting

3. Feature Set

Core Language Features

  • ✅ Variables and bindings (let)
  • ✅ Functions (named, anonymous)
  • ✅ Class-like object templates (make)
  • ✅ Conditionals (if/else)
  • ✅ Loops (while, for)
  • ✅ Error Handling (try/catch blocks)
  • ✅ Data types (number, string, bool, array, object)
  • ✅ Process and Desktop Integration (spawn, exec, open, open_file, time, random, convert, format)
  • ✅ Comments (//, /<em> </em>/) — text is preserved in AST as leadingComments on declarations for doc tooling
  • ✅ Operators (arithmetic, logical, comparison)
  • ✅ Standard library (show, len, range, etc.)
  • ✅ Interactive REPL shell environment (sesi)
  • ✅ Diagnostic Tools (--ast and --tokens pretty visualization)
  • ✅ Statement execution tracing (SESI_DEBUG=1 env variable)
  • ✅ prompt blocks (composable templates for concise formatting)
  • ✅ structured_output() (schema-guided structured output with JSON recovery and empty-object fallback on failure)
  • ✅ tool_call() (Fully functional function calling for tool use)
  • ✅ memory (simple multi-turn script memory and retrieval context management)

Reasoning-Native Features

  • ✅ model() calls (native model with configuration)
  • ✅ image() calls (native image generation with configuration)
  • ✅ images config key (multimodal vision input for model() and image())

Type System

  • ✅ Primitive types: number, string, bool, null
  • ✅ Collection types: array<T>, object<T>
  • ✅ Type inference
  • ✅ Union types: T | U
  • ✅ Optional types: T?

Module System

  • ✅ import / export
  • ✅ Lib support
  • ✅ Built-in modules
  • ✅ Multi-path module resolution (SESI_PATH, ~/.sesi/lib global library)

4. Target Language (Syntax)

4.1 Lexical Elements

Keywords

let if else while for fn make show import export async
prompt model image convert memory structured_output tool_call break continue try catch true false null await

These words are reserved and cannot be used as binding, function, parameter, template, prompt, memory, or import names. In particular, make is reserved exactly like prompt.

Identifiers & Literals

identifier: [a-zA-Z_][a-zA-Z0-9_]*
number: [0-9]+ | [0-9]*\.[0-9]+
string: "..." | '...'
comment: // ... | /* ... */

String Escapes & Multiline Rules

  • Supported escape sequences: \\n, \\t, \\r, \\\\, \\", \\'
  • Unknown escape sequences are runtime errors during lexing with line and column context
  • Strings can span multiple lines when a literal newline appears before the closing quote
  • Unterminated strings report the starting line and column of the string literal

4.2 Program Structure

program := statement*
statement := declaration | expression_statement | block_statement

4.3 Declarations

Variable Declaration

let_stmt := 'let' identifier (':' type)? ('=' expression)? (';' | newline)

Example:

let x = 10
let count: number = 10
let name: string = "Ada"
let y = 20
let z  // z is null initially

Function Declaration

fn_stmt := 'async'? 'fn' identifier '(' parameters ')' '->' type? block
parameters := (identifier ':' type ('=' expr)?)? (',' identifier ':' type ('=' expr)?)*

Example:

fn add(a: number, b: number) {show a + b}
fn greet(name: string = "World") {show "Hello," name}

Import/Export

import_stmt := 'import' (identifier | '{' identifiers '}') 'from' string
allow_stmt := 'allow' string 'in' with (identifier | '{' identifiers '}' | string)
export_stmt := 'export' (fn_stmt | let_stmt)

Example:

allow "math" in with {
  add, subtract
}
export fn multiply(a, b) {show a * b}

4.4 Control Flow

If Statement

if_stmt := 'if' expression block ('else' block)?

Loops

while_stmt := 'while' expression block
for_stmt := 'for' identifier 'in' expression block | 'for' identifier '=' expr 'to' expr block

Error Handling

try_stmt := 'try' block 'catch' '(' identifier ')' block

Loop Control

break_stmt := 'break'
continue_stmt := 'continue'

Example:

for i = 0 to 10 {show i}

try {
  let result = "Hello"
} catch (e) {
  show e
}

4.5 Expressions

Literals

literal := number | string | bool | null | array | object
array := '[' (expression (',' expression)*)? ']'
object := '{' (string ':' expression (',' string ':' expression)*)? '}'

Operators (Left to Right, Lowest to Highest Precedence)

expr := assignment
assignment := logical_or ('=' assignment)?
logical_or := pipe ('||' pipe)*
pipe := logical_and ('|' logical_and)*
logical_and := equality ('&&' equality)*
equality := comparison (('==' | '!=') comparison)*
comparison := addition (('<' | '>' | '<=' | '>=' | '<>') addition)*
addition := multiplication (('+' | '-') multiplication)*
multiplication := unary (('*' | '/' | '%') unary)*
unary := ('!' | '-' | 'await') unary | postfix
postfix := primary ('['expression']' | '.'identifier | '('args?')' | primary)*
primary := identifier | literal | '('expression')' | prompt | model | image | convert | memory | call

Object Templates

make_declaration := 'make' identifier '{' make_member* '}'
make_member := let_declaration | function_declaration

make declares a callable, class-like object template. Calling its name

creates a fresh object. start(self, ...) supplies the constructor parameters

and initializes the instance. Every method declares self first; method calls

bind it automatically.

make Person {
  let kind = "person"

  fn start(self, name) {
    self.name = name
  }

  fn greet(self) {
    return "Hello, " + self.name
  }
}

let ada = Person("Ada")
show ada.kind
show ada.greet()

Function Call

call := identifier '(' (expression (',' expression)*)? ')'

Prompt Block

prompt := 'prompt' identifier '{'content'}'
content := (string | expression | newline)

Example:

prompt codeReview {"Review this code for bugs: "code" Provide specific issues found."}

Model & Image Calls

model_call := 'model' '('STRING')' config_block? '{'prompt'}'
image_call := 'image' '('STRING')' config_block? '{'prompt'}'
convert := 'convert' '('(identifier | STRING)')' config_block? '{'file'}'
config_block := '{' config_entry (',' config_entry)* '}'
config_entry := (STRING | identifier) ':' expression

Config keys:

Key Applies to Type Description
thinkingLevel model string \ object Recommended: Effort level ("minimal", "low", "medium", "high")
temperature model, image number \*Will be deprecated in Gemini 3.x+\_ (Sampling temperature)
max_tokens model number Max output token count
top_k model number \*Will be deprecated in Gemini 3.x+\_
top_p model number \*Will be deprecated in Gemini 3.x+\_
ratio image string Aspect ratio e.g. "16:9"
size image string "512", "1K", "2K", "4K"
images model, image string \ array Local file path(s) passed as visual input
stream model bool \ fn Enable real-time streaming to stdout (true) or a callback function
system model, image string Provider-native system instruction

Example:

let result = model("gemini-3.8-flash") {images: "scan.png", thinkingLevel: "low"} {"Transcribe all visible text."}
let output = model("gemini-3.8-flash") {thinkingLevel: "medium"} {prompt}

Convert Expression

convert := 'convert' '('(identifier | STRING)')' config_block? '{'file'}'

The convert expression transforms documents or media files between different formats (e.g. images, audio, documents).

Config keys:

  • file_type: The input format extension (e.g. "md", "csv", "png", "wav"). If the input is a local file path, this key is optional and can be inferred from the file extension.
  • output_type: The target format extension (e.g. "html", "json", "jpg", "mp3"). This key is required.

Native document conversion pairs include md -> html, html -> md, html -> txt, csv -> json, tsv -> json, json -> csv, json -> tsv, json -> yaml, yaml -> json, svg -> html, html -> svg, and svg -> txt.

For image conversion, convert(media) also supports rasterizing svg file inputs to png, jpg, and jpeg, and wrapping raster image files such as png, jpg, jpeg, gif, webp, bmp, tiff, and avif into SVG output.

Example:

let html = convert(doc) {file_type: "md", output_type: "html"} {"# Heading\nHello world"}
let json = convert(doc) {file_type: "csv", output_type: "json"} {"name,age\nAlice,30"}
let yaml = convert(doc) {file_type: "json", output_type: "yaml"} {"[{\"name\":\"Alice\"}]"}
let markdown = convert(doc) {file_type: "html", output_type: "md"} {"<h1>Heading</h1><p>Hello world</p>"}
let converted_file = convert(doc) {file_type: "md", output_type: "html"} {"input.md"}
let rasterized_svg = convert(media) {output_type: "png"} {"logo.svg"}

Await Expression

await_expr := 'await' expression

The await expression is used to block execution and resolve the value of a Sesi Promise returned by an asynchronous function.

Example:

async fn getGreeting(name) {
  return "Hello, " + name
}

let p = getGreeting("Alice") // returns a Sesi promise
let greeting = await p // blocks and resolves to "Hello, Alice"

Structured Output

structured_output := 'structured_output' '('schema')' '('expression')'
schema := '{' (identifier ':' type (',' identifier ':' type)*)? '}'

Example:

let rawJson = "{\"projectName\": \"Sesi\", \"version\": \"1.9.0\", \"status\": \"active\"}"
let parsedRegistry = structured_output({projectName: string, version: string, status: string})(rawJson)

Tool Call

The tool_call expression allows native Sesi functions registered via define_tool to be invoked programmatically.

// 1. Define the native Sesi function
fn calculateTax(amount: number, rate: number) -> number { return amount * rate }

// 2. Register the function as a tool
define_tool("calculateTax", calculateTax, "Calculate tax based on amount and rate")

// 3. Invoke the tool programmatically
let taxAmount = tool_call(calculateTax)(100, 0.08)

The tool invocation is synchronous and executes the registered function within the current interpreter context. This mechanism can be used by AI agents to perform side-effects, but it functions independently as a core language primitive.

Registered functions can also be orchestrated automatically by a model call:

let answer = model("gemini-3.8-flash") {tools: list_tools(), max_tool_calls: 4} {"What is 8% tax on $125?"}

tools accepts registered tool names, registered function values, provider schemas, or true for every registered tool. For registered tools, Sesi derives parameter schemas from type annotations, maps model-supplied named arguments to function parameters, executes the function, and resumes the model with the result. This repeats until the model returns text. max_tool_calls defaults to 8; exceeding it raises a runtime error. Automated calls to sensitive system functions remain forbidden.

Pipe Operator

The pipe operator | passes the result of the left expression as the first argument to the function call on the right.

pipe_expr := expression '|' function_call_or_identifier

Example:

fn increment(x) { return x + 1 }
fn double(x) { return x * 2 }

let result = 5 | increment | double // evaluates to 12

Rule of Thumb:

Use | for data pipelines: arrays, strings, objects, or multi-step transformations (data | filter | map | show).

Use standard syntax () for math, boolean logic (!, &&, ||), comparisons (==, !=), and inline checks.

Memory (State Management)

memory := 'memory' identifier ('{'expressions'}')?

Example:

memory conversation {"Previous messages here..."}
let userInput = "New message added."
let response = model("gemini-3-flash-preview") {conversation "New question: "userInput}
conversation = conversation + "Assistant:" + response

Memory bindings automatically compact after an update when their estimated token count exceeds the configured budget. Older content is summarized while a recent tail remains verbatim:

memory conversation {"System: Preserve project decisions."}
memory_config("conversation", {"max_tokens": 8000, "target_tokens": 4800, "summary_model": "gemini-3.5-flash-lite"})

max_tokens defaults to 900000, target_tokens defaults to 60% of that limit, and automatic summarization is enabled by default. A failed summary leaves the original memory unchanged. memory_trim() remains available for explicit compaction.

4.6 Type Annotations

type := primitive_type | collection_type | union_type | optional_type
primitive_type := 'number' | 'num' | 'string' | 'str' | 'bool' | 'null' | 'any'
collection_type := 'array' '<' type '>' | 'object' '<' type '>'
union_type := type ('|' type)
optional_type := type '?'

Type aliases: num is an alias for number, str is an alias for string, and any accepts any value. These can be used interchangeably in function signatures, variable annotations, and return types.

Variable annotations go between the variable name and =. They are optional, so either of these declarations is valid:

let total: number = 42
let label = "draft"

5. Expression Evaluation Rules

  1. Short-circuit evaluation: && and || short-circuit
  2. Type coercion: Automatic for numeric operations; explicit for string/number
  3. Null propagation: Operations on null return null (no exceptions in v1.x)
  4. Model responses: Always returned as strings initially; structured_output provides type safety

6. Scope and Binding

  • Global scope: Module level
  • Function scope: Within function definitions
  • Block scope: Within blocks (if/while/for)
  • Lexical scoping: Inner scopes shadow outer scopes
  • Closure support: Functions capture enclosing scope

7. Runtime Semantics

Execution Order

  1. Tokenize (lexer)
  2. Parse (parser) → AST
  3. Evaluate (interpreter)
  4. Model calls are blocking (no async in v1)

Memory Model

  • Stack: Local variables, function parameters
  • Heap: Arrays, objects, strings
  • Reasoning Context: Implicit conversation history per memory binding

Error Handling (V1 Simple)

  • Runtime and model errors can be caught with try/catch
  • Model errors throw when Gemini returns no text or a non-STOP finish reason
  • read_file(), write_file(), list_dir(), open(), and open_file() throw on filesystem or launch failure
  • structured_output() currently logs parsing failures and returns {} if recovery fails

Desktop Launching

open() and open_file() hand a target to an external desktop application and return true after the operating system accepts the launch request. They do not wait for the application to exit.

open("https://code-with-sesi.netlify.app")
open("reports/dashboard.html", {mode: "browser", browser: "Firefox"})

open_file("README.md", {editor: "Visual Studio Code"})
open_file("favicon.png", {viewer: "Preview"})

Both functions are disabled in safe mode and require sesi -l or sesi --local.

open(target, options?) accepts an http, https, ftp, file, or mailto URL. When its target is not a URL, it behaves like open_file() and resolves an existing local path through the filesystem safety checks. open_file(path, options?) accepts only an existing local path.

The optional settings object supports:

Key Type Meaning
browser string Preferred browser application
editor string Preferred text editor application
viewer string Preferred viewer application
image_viewer string Alias for viewer
mode string "auto", "browser", "editor", "viewer", or "image_viewer"

In "auto" mode, Sesi uses the requested image viewer for image extensions, the requested editor for text extensions, or the requested browser for browser-friendly extensions. If no matching application is specified, the operating system default is used.

8. Built-in Functions

show(any)                    // Output to stdout
debug()                       // Pauses and opens interactive REPL debugger
len(array | string | object)  // Length
range(number) -> array        // [0, 1, ..., n-1]
type(any) -> string           // Type name
str(any) -> string            // Convert to string
num(any) -> number            // Convert to number
float(any) -> number          // Convert to floating-point number
bool(any) -> bool             // Convert to bool
keys(object) -> array         // Object keys
values(object) -> array       // Object values
push(array, any)              // Add element
append(array|string, any)     // Append to array or concatenate to string
pop(array) -> any             // Remove last
join(array, string) -> string // Join with separator
split(string, string) -> array // Split by separator
regex(string, string, string|object?) -> array|bool|string // Regular-expression operations
tokenize(string, string|object?) -> array // Local OpenAI-compatible token IDs
count_tokens(string, string|object?) -> number // Native OpenAI/Gemini request count
estimate_tokens(string, string|object?) -> number // Explicit local approximation
estimate_cost(string, number|string, number|string?, object?) -> object // Token cost estimate
model_usage() -> object|null   // Latest provider-reported usage and estimated cost
gif(string|array, string, object?) -> string // FFmpeg-backed animated GIF creation
video(string) {object?} {expression} -> string // AI video generation; returns Base64 MP4
video(string|array, string, object?) -> string // FFmpeg-backed video creation/transcoding overload
ffmpeg(array, object?) -> object // Structured raw FFmpeg invocation
matrix_dot(array, array) -> array // Native rectangular matrix multiplication
matrix_transpose(array) -> array // Native matrix transpose
matrix_add(array, array) -> array // Native addition with single-row bias broadcasting
matrix_sub(array, array) -> array // Native same-shape subtraction
matrix_mul_elements(array, array) -> array // Native elementwise multiplication
matrix_scale(array, number) -> array // Native scalar multiplication
matrix_sigmoid(array) -> array // Native elementwise sigmoid
matrix_dsigmoid(array) -> array // Native sigmoid-output derivative
matrix_sum_rows(array) -> array // Native column sums as a single-row matrix
matrix_mse(array, array) -> number // Native mean squared error
to_upper(string) -> string       // Convert to uppercase
to_lower(string) -> string       // Convert to lowercase
trim(string) -> string        // Trim whitespace
slice(collection, number, number?) -> collection // Slice string or array
swap(string, string, string) -> string // Replace all target substrings
contains(string, string) -> bool       // Check if string contains substring
locate(string, string) -> number       // First index of substring, or -1
map(array, fn) -> array       // Transform array elements
filter(array, fn) -> array    // Filter array elements
reduce(array, fn, any?) -> any // Accumulate array elements
find(array, fn) -> any        // Find matching element
retry(fn, number | object) -> any // Execute function with retry and backoff
lazy(fn, ...args) -> lazy     // Create a memoized delayed computation
force(any) -> any             // Resolve lazy values and promises
timeout(fn, number, any?) -> any // Run function with millisecond deadline
profile(string, fn) -> any    // Measure function runtime and return its result
profile_start(string) -> string // Begin manual profiling section
profile_end(string) -> object // End manual profiling section
profile_report(string?) -> array | string // Return profiler measurements
read_file(string, string?) -> string    // Read file contents (text or base64)
encrypt(string, string) -> string       // AES-256-CBC encrypt UTF-8 string content
decrypt(string, string) -> string       // AES-256-CBC decrypt iv:ciphertext content
write_file(string, string) -> bool // Write file contents
append_file(string, string) -> bool // Append string content to file
write_image(string, string) -> bool // Write base64 image data to file
open(string, object?) -> bool    // Open URL or local file in external app; local mode only
open_file(string, object?) -> bool // Open existing local file in external app; local mode only
list_dir(string) -> array<string> // List directory contents
make_dir(string) -> bool          // Create directory (recursive)
spawn(string) -> number           // Concurrent process creation
exec(string) -> string            // Synchronous shell execution
run(string) -> string             // Exact alias of exec
get_ext(string) -> string         // Lowercase extension without a dot
exists(string) -> bool            // Sandbox-aware path existence check
zip(source, destination?, operation?) // Create, list, or extract archives
sesi(string, bool?, bool?) -> string // Synchronous in-process Sesi execution or compile check
python(string, args) -> string    // Inline Python code execution
js(strings, args) -> string       // In-proccess Javascript execution
time() -> number                  // Current Unix timestamp
random() -> number                // Random float (0.0 to 1.0)
trunc(value, number?) -> any      // Truncate number (integer part) or string (char limit)
convert() -> bool                 // Convert between formats
memory_search(string, string, number?) -> array // Semantic similarity search over memory entries
memory_config(string, object?) -> object        // Configure automatic memory summarization
memory_trim(string, number?) -> string          // Context window management with auto-summarization

Built-in Global Variables

  • args

9. Module System

Runtime module execution and standard library modules are fully implemented and natively supported in v1.x.

Defining Modules

// math.sesi
export fn add(a, b) {show a + b}
export fn multiply(a, b) {show a * b}
export let PI = 3.14159

Importing Modules

You can import variables and functions from other modules using traditional import or the scoped library allow syntax:

// Option 1: import named bindings directly
import {
  add,
  multiply,
  PI
} from "math"
let result = add(10, 20)

// Option 2: allow module to bind under a scoped library namespace
allow "math" in as Math
let result = Math.add(10, 20)

// Option 3: allow module to bind specific names directly
allow "math" in with {
  add, multiply
}
let result = add(10, 20)

Built-in Standard Library Modules

allow "std/time" in as Time    // Time/date functions
allow "std/math" in as Math    // Math operations
// JSON conversion uses the built-in from_json and to_json functions.
allow "std/draw" in as Draw    // SVG/Pixel creation
allow "std/audio" in as Audio  // Audio synthesis
allow "std/theory" in as Music   // Music Theory
allow "std/terminal" in as Term  // Terminal options
allow "std/base64" in as Base64 // Base64 encode/decode
allow "std/api" in as API       // FastAPI-style HTTP API framework
allow "std/game" in as Game     // Babylon-powered 3D desktop games (optional package)

std/game is an imperative native-object module. Scenes use left-handed coordinates with Y up, +X right, and +Z forward. Development-time relative asset paths and build outputs resolve from the current working directory; packaged assets resolve from the staged application root. Member reads and writes on handles are dispatched through guarded native hooks in both execution engines. Handles preserve identity, enumerate only allowlisted properties, reject protected prototype names, and raise typed errors for disposed, read-only, or cross-scene access. Development execution and desktop builds require -l; the optional runtime is installed with npm install @misterscan/sesi-game. See getting-started/GAME.md.

Module Resolution Order (v1.x)

When you write allow "mymodule" in with {x} , Sesi searches for mymodule.sesi in the following order, stopping at the first match:

Priority Location Description
1 Script's own directory Same folder as the currently running .sesi file
2 Current working directory The directory you ran sesi from
3 SESI_PATH Semicolon-separated (Windows) or colon-separated (Unix) list of additional directories
4 ~/.sesi/lib Global shared library directory — available system-wide

This means imports always resolve correctly regardless of where you run sesi from.

Global Library: ~/.sesi/lib

The global library directory (C:\Users\<you>\.sesi\lib on Windows, ~/.sesi/lib on Unix) lets you maintain shared modules that are importable from any project on your system.

To install a module globally, copy it to the lib directory:

# Windows
copy mymodule.sesi $env:USERPROFILE\.sesi\lib\

# Unix / macOS
cp mymodule.sesi ~/.sesi/lib/

Then import it from any project without copying the file:

// Works from any folder anywhere on your system
allow "mymodule" in with {
  function1,
  function2,
  function3
}
allow "another-module" in as Name

Custom Library Paths: SESI_PATH

For team or monorepo setups, set the SESI_PATH environment variable to point to one or more shared library directories:

# Windows — add to your shell profile for persistence
$env:SESI_PATH = "C:\MyLibs\sesi-shared;C:\Projects\common"

# Unix / macOS
export SESI_PATH="/mylibs/sesi-shared:/projects/common"

Multiple paths are separated by ; on Windows and : on Unix.

Sub-module Resolution

When a module is loaded from any search path, its own imports are resolved relative to that module's directory first. This means modules can safely import their own siblings without any path configuration.

10. Reasoning Features Details

Prompt Blocks

Prompts are composable message templates:

prompt generate {"Craft a full report on the following: "sourceText}
prompt summarize {"Summarize this in 3 sentences: "sourceText}
prompt combined {summarize" Now "generate}

Model & Image Calls

Model calls can take optional configuration parameters (written on a single line) followed by one or more prompts/strings.

// Model call with native thinking effort level
let response = model("gemini-3.8-flash") {thinkingLevel: "low"} {"Say hello"}
show response  // Returns string

let logo = image("gemini-3.1-flash-image") {ratio: "1:1", size: "512"} {"A vector logo"}
write_image("logo.png", logo)
show "Image written to logo.png"

Config Block Options:

  • thinkingLevel: string ("minimal", "low", "medium", "high") or legacy object with keys "thinking" and "level". Natively configures Gemini's reasoning budget.
  • max_tokens: number (maximum response tokens)
  • images: string or array<string> (paths to multimodal vision input files)
  • cache: bool (set to false to explicitly bypass Sesi Logic Caching)
  • stream: bool | fn (set to true to stream tokens to standard output, or pass a Sesi function reference to handle incoming chunks)
  • temperature: Will be deprecated in Gemini 3.x+, use thinkingLevel instead. — reasoning is pre-optimized for defaults.
  • top_k / top_p: Will be deprecated in Gemini 3.x+, use thinkingLevel instead. — reasoning is pre-optimized for defaults.

Speech and Transcription

Sesi provides built-ins for spoken output and transcription.

speech("Analysis complete")
let transcript = from_speech("interview.wav", "en")
show transcript

  • speech(text, voice = null, gemini_model = null) speaks through the operating system's local voice tool, or uses the optional Gemini model.
  • from_speech(audio_path, language = null, gemini_model = null) transcribes with nodejs-whisper, or the optional Gemini model.

Reasoning with Structured Output

let result = structured_output({title: string, category: string, confidence: number})
(model("gemini-3.5-flash-lite") {"Extract metadata from this text: "text})
show result.title       // Access fields
show result.confidence  // Type-safe access

Reasoning with Tool Calling

While tool_call() is a core language feature, it is the primary interface for AI agents to interact with your Sesi scripts. When an agent is given access to tools, it can decide to invoke them based on its reasoning process.

fn calculateTax(amount: number, rate: number) -> number { return amount * rate }

// Register as a tool
define_tool("calculateTax", calculateTax, "Calculate tax based on amount and rate")

// Agent-driven usage:
// The model decides to invoke 'calculateTax' with specific parameters
let taxAmount = tool_call(calculateTax)(model("gemini-3.5-flash-lite") {"Extract tax amount and rate from text"}, 0.08)

Reasoning with Memory

memory chat {"System: You are a helpful assistant."}
fn askQuestion(question: string) {
  let response = model("gemini-3-flash-preview") {chat "User:" question}
  chat = chat + "Assistant:" + response
  return chat
}

11. Examples

Example 1: Simple Computation

let x = 10
let y = 20
show x + y  // Output: 30

Example 2: Function with Reasoning

let text = "Reasoning is transforming industries!"
fn analyzeText(text: string) -> string {return model("gemini-3.8-flash") {thinkingLevel: "low"} {"Analyze this text and return key insights: "text}}
show analyzeText()

Example 3: Reasoning with Structured Output

let userInput = "I love working with Sesi!"
let sentiment = structured_output({label: string, score: number})(model("gemini-3-flash-preview") {"Analyze sentiment of: "userInput})
show sentiment.label
show sentiment.score

12. Undefined Behavior & Limitations

  • No custom types: Only built-in types are supported natively.
  • No pattern matching: Basic if/else only.
  • No generics: Array and object collections are untyped at runtime.
  • Limited introspection: Basic type() only.
  • No macros: No compile-time code generation.
  • Single-threaded runtime: Execution per script event loop is single-threaded. System-level concurrency is handled via multi-process spawn().
  • No garbage collection tuning: Rely on Node.js GC.

13. Compatibility Notes

  • Sesi programs run on Node.js 20+, using local models relies on Node.js 22+
  • Requires @google/genai SDK v2.0.1+
  • Requires valid Gemini API key (GEMINI_API_KEY env var)