MALDA™ Reference Manual

The AI-First Programming Language - Version 1.0.11

13. Built-in Functions

This chapter is the stdlib catalog: conversion, math, strings, files, JSON, dates, and error helpers. Agent tools, task plans, durable workflow operations, and ui.* are indexed at the end of the chapter and documented in their home chapters.

13.1 Type Conversion

var num = int("123");      // Convert string to integer
var floatVal = float("3.14");  // Convert string to float
var str = string(42);      // Convert number to string

13.1.1 Safe Integer Conversion Helpers

Use these helpers when input may be empty, null, or malformed.

var page = toIntOr(query.page, 1);          // Fallback when null/empty/unparseable
var limit = toIntOr(query.limit, 50);       // Always returns integer
var ownerId = toIntOrNull(query.ownerId);   // Returns null when missing/unparseable

13.2 Stdlib Namespaces and Flat Aliases

Most of the standard library is reachable in two spellings: a namespaced call through a module object, and a flat global of the same name. Both resolve to the same implementation and behave identically at runtime.

print(math.sqrt(16));                          // namespaced
print(sqrt(16));                               // flat alias, same result

print(str.join(str.split("a,b", ","), "|"));   // a|b
print(io.readFile("config.json"));

The module objects

ModuleCovers
mathRounding, trigonometry, aggregates, random helpers, LLM math, and the constants math.PI, math.E, math.TAU, math.INF, math.NaN
strCase, trimming, splitting and joining, padding, regex helpers, similarity, base64, md5 / sha256
ioprint, input, file and path helpers, glob, grep, environment variables, git helpers
pdfextractText — read text from a PDF file (digital text layer; no OCR)
docextractText — read text from a Word .docx (Open XML; not legacy .doc)
resultok, err, map, unwrapOr, isOk, isErr — see 13.19.1
optionsome, none, map, unwrapOr, isSome, isNone — see 13.19.1

Math (capital M) is a deprecated alias for the same object as math.

Which flat names are deprecated

Only the flat names that have a math., str., or io. counterpart are considered deprecated aliases. Calling one produces an IDE and language-server warning from source malda-style, in the form Prefer 'io.print(...)' instead of 'print(...)' (deprecated flat alias). The warning is advisory: nothing is removed at runtime and the transpilers accept both spellings.

The affected names, mirroring MaldaLang/BuiltIns/StdLibNamespaces.cs:

Every other built-in in this chapter — sleep, runCommand, parseJson, the agent and workflow helpers, and so on — has no module counterpart and no deprecation attached to it.

Convention used in this manual: examples throughout the manual and in Examples/ use the flat spelling (print(...), sqrt(...)) because it is shorter and it is what existing MALDA code looks like. Read those as equivalent to the namespaced form. In new code, prefer the namespaced spelling if you want the editor to stay warning-free.

13.3 Mathematical Functions

Math operations are available as math.* (preferred), deprecated flat built-ins, and Math.* (deprecated alias).

// Flat built-ins (deprecated flat alias; still supported)
var absVal = abs(-5);              // Absolute value
var total = sum([1, 2, 3, 4]);     // 10
var avg = average([1, 2, 3, 4]);   // 2.5
var maxVal = max(10, 20);          // Maximum of two values
var maxArr = max([10, 20, 5]);     // Maximum in a numeric array
var minVal = min(10, 20);          // Minimum of two values
var minArr = min([10, 20, 5]);     // Minimum in a numeric array
var powVal = pow(2, 3);            // Power: 2^3 = 8
var sqrtVal = sqrt(16);            // Square root: 4

// Extended math (rounding and sign)
var f = floor(3.7);                // 3
var c = ceil(3.2);                 // 4
var r = round(2.5);                // 2 (banker’s rounding, .NET default)
var t = trunc(-3.9);               // -3
var s1 = sign(-10);                // -1
var s2 = sign(0);                  // 0
var s3 = sign(10);                 // 1

// Extended math (exponential and logarithm)
var e = exp(1);                    // ~2.718281828 (Math.E)
var ln = log(Math.E);              // Natural log, ~1
var lg = log10(1000);              // Base-10 log, 3
var lb = log2(8);                  // Base-2 log, 3

// Extended math (trigonometry, radians)
var halfPi = degToRad(90);         // Convert degrees to radians
var s = sin(halfPi);               // ~1.0
var c0 = cos(0);                   // ~1.0
var t = tan(0);                    // 0.0
var a = atan2(1, 1);               // ~PI/4

// Inverse trigonometry (single argument, result in radians)
var as1 = asin(1);                 // ~PI/2
var ac1 = acos(1);                 // 0.0
var at1 = atan(1);                 // ~PI/4
var outOfDomain = asin(2);         // NaN: no error is raised

// Extended math (utility)
var h = hypot(3, 4);               // 5 (sqrt(3*3 + 4*4))
var cl1 = clamp(-1, 0, 10);        // 0
var cl2 = clamp(5, 0, 3);          // 3
var rad = degToRad(180);           // PI
var deg = radToDeg(Math.PI / 2);   // 90

// LLM-oriented math helpers
seed(42);                          // Deterministic random stream
var n = randn(0.1);                // Gaussian random ~ N(0, 0.1^2)
var inv = rsqrt(16);               // 0.25 (1/sqrt(x))
var idxMax = argmax([0.1, 0.7, 0.2]); // 1
var idxMin = argmin([0.1, 0.7, 0.2]); // 0
var probs = softmax([2.0, 1.0, 0.0]); // Probability array
var lse = logSumExp([2.0, 1.0, 0.0]); // Stable log(sum(exp(x)))
var ce = crossEntropyFromLogits([2.0, 1.0, 0.0], 0); // NLL for target index
var sampled = randomChoiceWeighted([0.1, 0.7, 0.2]); // Weighted sampled index

// All trigonometric functions take angles in radians, accept an integer or a
// float, and return a float. Out-of-domain input yields NaN rather than an error.

// Preferred: math.* module (Math.* is deprecated alias)
var cCirc = 2 * math.PI * r;
var cCircLegacy = 2 * Math.PI * r; // deprecated alias
var total2 = Math.sum([1, 2, 3]);  // Same as sum(...)
var avg2 = Math.average([1, 2, 3]); // Same as average(...)
var powVal2 = Math.pow(2, 3);      // 8
var sqrtVal2 = Math.sqrt(16);      // 4
var floorVal = Math.floor(3.7);    // 3
var sinVal = Math.sin(degToRad(90)); // ~1.0
var rand = Math.random();          // Random float between 0.0 and 1.0
var randInt = Math.randomInt(1, 10);   // Random integer between 1 and 10 (inclusive)
var randFloat = Math.randomFloat(0.0, 100.0); // Random float between 0.0 and 100.0
var n2 = Math.randn(0.1);          // Same as randn(0.1)
var probs2 = Math.softmax([2.0, 1.0, 0.0]); // Same as softmax(...)

sum(values) returns the total of a numeric array. average(values) returns the arithmetic mean of a non-empty numeric array as a float.

max and min support both (a, b) and (values) forms. When passed a single array argument, the array must be non-empty and contain only numbers.

For numeric arrays, these aggregate operations are also available as methods: values.sum(), values.average(), values.min(), and values.max().

13.3.1 LLM-oriented Math Helpers (Reference)

These helpers are available as math.softmax(values) (preferred), flat softmax(values) (deprecated), and Math.softmax(values) (deprecated alias).

seed(seedValue)

Sets the global pseudo-random seed used by random(), randomInt(), randomFloat(), randn(), and randomChoiceWeighted(). Argument must be an integer. Returns null.

seed(42);
print(random());       // Deterministic across runs with same seed
print(Math.random());

randn(std?, mean?)

Generates a normally distributed random float using Box-Muller transform. Signature: randn(std = 1.0, mean = 0.0). Returns a float.

var z1 = randn();          // N(0, 1)
var z2 = randn(0.1);       // N(0, 0.1^2)
var z3 = randn(0.1, 1.5);  // N(1.5, 0.1^2)

rsqrt(x)

Returns reciprocal square root: 1 / sqrt(x). Useful in attention and normalization formulas. Returns a float.

print(rsqrt(16));      // 0.25
print(Math.rsqrt(4));  // 0.5

argmax(values)

Returns the index of the maximum value in a non-empty numeric array. If multiple values tie for maximum, returns the first index. Returns an integer.

print(argmax([0.1, 0.7, 0.2]));   // 1
print(argmax([3, 3, 1]));         // 0 (first max)

argmin(values)

Returns the index of the minimum value in a non-empty numeric array. If multiple values tie for minimum, returns the first index. Returns an integer.

print(argmin([0.1, 0.7, 0.2]));   // 0
print(argmin([3, 1, 1]));         // 1 (first min)

logSumExp(values)

Computes numerically stable log(sum(exp(values[i]))) over a non-empty numeric array. Returns a float.

var lse = logSumExp([2.0, 1.0, 0.0]);
print(lse);

softmax(values, temperature?)

Computes softmax probabilities from a non-empty numeric array. Optional temperature defaults to 1.0 and must be > 0. Returns an array of floats that sum to approximately 1.

var p1 = softmax([2.0, 1.0, 0.0]);      // temperature = 1.0
var p2 = softmax([2.0, 1.0, 0.0], 0.5); // Sharper distribution
print(p1);

crossEntropyFromLogits(logits, targetIndex)

Computes negative log-likelihood directly from logits for one target class: -log(softmax(logits)[targetIndex]). targetIndex must be a valid integer index in the logits array. Returns a float.

var loss = crossEntropyFromLogits([2.0, 1.0, 0.0], 0);
print(loss);

randomChoiceWeighted(weights)

Samples and returns an index from a non-empty numeric weight array. All weights must be >= 0 and their total must be > 0.

var idx = randomChoiceWeighted([0.1, 0.7, 0.2]); // Often 1
print(idx);

Error behavior: these helpers throw runtime errors for invalid argument counts/types, empty arrays where not allowed, out-of-range target indices, non-positive softmax temperature, negative weights, or zero total weight.

13.4 String Functions

String operations are available as flat built-in functions (e.g. upper(s)) and as extension-style methods on string values (e.g. s.upper()). Both forms work in the interpreter and in transpiled code.

var len = length("Hello");      // String length
var upper = upper("hello");     // Convert to uppercase
var lower = lower("HELLO");     // Convert to lowercase
var trimmed = trim("  hello  "); // Remove leading and trailing whitespace (returns "hello")
var substr = substring("Hello", 0, 3);  // Extract substring: start at index 0, take 3 characters (returns "Hel")
// substring(text, startIndex, length) - third parameter is COUNT/LENGTH, not end index
var singleChar = substring("Hello", 1, 1);  // Get single character at index 1 (returns "e")
var pos = indexOf("hello world", "world");  // Find position (returns 6, 0-indexed)
var notFound = indexOf("hello", "xyz");     // Returns -1 if not found
var replaced = replace("Hello world", "world", "MALDA");  // Replace all occurrences (returns "Hello MALDA")
var parts = split("a,b,c", ",");  // Split string into array (returns ["a", "b", "c"])
var normalized = normalizeText("  Città, 42! ");  // "citta 42"
var words = tokenize("Uno, due, tre!");  // ["uno", "due", "tre"]
var score = similarity("equazione lineare", "equazioni lineari");
var numbers = extractNumbers("x=12, y=3.5");  // [12, 3.5]
var joined = parts.join(",");  // Join array into string (returns "a,b,c")
// Null-safe boundary helpers (prefer str.* spelling):
var asText = str.text(maybeNull);       // null → "" (unlike string(null) → "null")
var cleaned = str.trimText(maybeNull);  // null → ""; else string then trim

str.text(value) coerces any value to a string, mapping null to "". str.trimText(value) is str.trim(str.text(value)). Use these at env / JSON / CLI boundaries instead of nesting null checks before str.trim.

Extension-style string methods

The functions length, upper, lower, trim, substring, indexOf, replace, split, startsWith, endsWith, padStart, padEnd, and repeat can also be called as methods on any string value. The receiver is treated as the first argument. This is similar to extension methods in VB.NET/C#.

var name = "pippo";
var nameUpper = string(name).upper();   // same as upper(string(name)) or upper(name)
print("hello".upper());                 // HELLO
print("HELLO".lower());                 // hello
var s = "Hello";
print(s.length());                      // 5
print(s.substring(0, 3));               // Hel
print(s.indexOf("ll"));                 // 2
print(s.replace("He", "Ye"));           // Yello
print("abc".repeat(2));                 // abcabc
var f = "world".upper;                  // method as value
print(f());                             // WORLD

Calling an unsupported member on a string (e.g. s.foo()) causes a runtime error.

Regular Expression Functions

var matches = regexMatch("test123", "\\d+");  // Check if pattern matches (returns true)
var result = regexReplace("abc123", "\\d+", "456");  // Replace matches (returns "abc456")
// Use $1, $2, etc. for capture groups in replacement
var swapped = regexReplace("John Doe", "(\\w+) (\\w+)", "$2, $1");  // Returns "Doe, John"
var matches = regexFind("test123 test456", "\\d+");  // Find all matches (returns array of match objects)

Additional String Functions

var starts = startsWith("Hello", "He");      // Check if string starts with prefix (returns true)
var ends = endsWith("Hello", "lo");         // Check if string ends with suffix (returns true)
var padded = padStart("5", 3, "0");        // Pad string to length from left (returns "005")
var padded2 = padEnd("5", 3, "0");          // Pad string to length from right (returns "500")
var repeated = repeat("Hi", 3);             // Repeat string N times (returns "HiHiHi")

Text Matching Helpers

var normalizedText = normalizeText("  Città, 42! ");   // "citta 42"
var tokens = tokenize("CPU, RAM e disco");            // ["cpu", "ram", "e", "disco"]
var overlap = tokenOverlap("cpu memoria cache", "cache cpu");
print(overlap.sharedCount);                           // 2
print(overlap.jaccard);                               // 0.66...
var sim1 = similarity("equazione lineare", "equazioni lineari");
var sim2 = similarity("processore", "processor", "char-ngram");
var nums = extractNumbers("x=12, y=3.5, z=-2");      // [12, 3.5, -2]

Path Functions

var filename = getFileName("ReferenceManual/09-functions.html");  // Returns "09-functions.html"
var dir = getDirectoryName("ReferenceManual/09-functions.html");  // Returns "ReferenceManual"
var dir2 = getDirectoryName("09-functions.html");  // Returns "" (empty for files in current directory)
var joined = pathJoin("dir1", "dir2", "file.txt");  // Join path segments (returns "dir1/dir2/file.txt" or "dir1\\dir2\\file.txt" on Windows)
var normalized = pathNormalize("./dir/../file.txt");  // Normalize path (returns absolute path)
var exists = pathExists("file.txt");        // Check if path exists (file or directory)
var ext = pathGetExtension("file.txt");     // Get file extension (returns ".txt")
var under = isPathUnder("brain", "brain/notes/a.md");  // true when path resolves under root (disk or embed:)
var escape = isPathUnder("brain", "brain/../secret.txt");  // false

isPathUnder(root, path) — Returns true when path resolves to the same location as root or to a descendant. Uses full-path comparison with a directory-separator boundary (so demo does not match demo-evil). Works for disk paths and embed:<alias>/… virtual roots. Returns false on invalid or cross-scheme pairs.

MALDA home and config

These functions support the personal assistant and CLI config directory ~/.malda.

var home = getMaldaHome();   // Returns "~/.malda" (e.g. C:\Users\You\.malda on Windows)
var config = getMaldaConfig(); // Returns config object from ./.malda/config.json or ~/.malda/config.json, or null

getMaldaHome() — Returns the path to the MALDA user directory (no arguments).

getMaldaConfig() — Reads the first existing config file from ./.malda/config.json or ~/.malda/config.json, parses it as JSON, and returns the result as an object. Returns null if neither file exists or parsing fails. Use it to read providers.openrouter.apiKey, agents.defaults.model, tools.web.search.apiKey, etc.

getAssistantMemory(path?) — Returns a GraphMemory instance initialized with MALDA_MEMORY_EMBED (default hash) and loaded from ~/.malda/memory/assistant when artifacts exist. Optional path overrides the storage base path (without extension).

Skills

These functions support loading skills from ~/.malda/skills/.

var names = getSkillNames();   // Returns array of skill base names, e.g. ["github", "weather"]
var skill = loadSkill("github"); // Loads ~/.malda/skills/github.malda, returns object with module globals (e.g. skill.tools, skill.agent)
var skills = loadSkillsFromDir(); // Scans ~/.malda/skills/*.malda; each entry has name + exports (or error)

getSkillNames() — Returns an array of strings: the base names (without .malda) of all .malda files in ~/.malda/skills/. Returns [] if the directory does not exist or is empty. No arguments.

loadSkill(name) — Loads the skill file ~/.malda/skills/<name>.malda, runs it in an isolated environment, and returns an object whose properties are the module’s global variables. Convention: skills export a tools array (and optionally agent). Returns null if the file does not exist or name is empty. One argument: the skill name (string).

loadSkillsFromDir(path?) — Scans a directory (default ~/.malda/skills) for *.malda files and returns an array of objects. Each object includes name plus the skill module globals (tools, agent, etc.). On load failure, the object has name and error instead. Optional first argument: directory path (string).

13.5 Environment and Host

How-to and the getEnv / str.trim footgun: 12.5 Environment and Host.

var apiKey = getEnv("OPENAI_API_KEY");  // string, or null when unset
var apiKeyOr = io.getEnvOr("OPENAI_API_KEY");  // "" when unset (optional 2nd arg = default)
var hasKey = hasEnv("API_KEY");         // Check if environment variable exists

io.getEnvOr(name, default?) — same lookup as getEnv, but never returns null: missing variables yield default (empty string when omitted). Prefer this before str.trim / other string sinks.

13.5.1 Host Information

Argument-less built-ins describe the machine and invocation the program is running under. Passing any argument raises an error.

var host = getHostPlatform();
print(host.os);              // Operating system identifier
print(host.arch);            // Process architecture
print(host.pathSeparator);   // "\" on Windows, "/" elsewhere
print(host.description);     // Full OS description string

var args = getCommandLineArgs();
// Arguments passed to the program, excluding the program name itself
if (args.length > 0) {
    print("first argument: " + args[0]);
}

// Folder of the .malda script (interpreter) or of the compiled .exe (transpile)
var programDir = getProgramDirectory();
var modelPath = io.pathJoin(programDir, "bge-m3-Q4_K_M.gguf");

getHostPlatform() returns an object with the four fields shown above. getCommandLineArgs() returns an array of strings and is the way to read CLI arguments from a MALDA program, in both interpreted and transpiled runs. getProgramDirectory() returns the absolute directory of the running .malda source file under the interpreter, or AppContext.BaseDirectory (the folder containing the compiled executable) after malda compile.

13.5.2 Web search (Brave Search API)

webSearch(query, apiKey?) — Performs a web search using the Brave Search API. query is the search string. apiKey is optional; if omitted, the key is taken from (in order) the apiKey argument, the BRAVE_SEARCH_API_KEY environment variable, or tools.web.search.apiKey in ~/.malda/config.json (see Personal Assistant and CLI). Returns an object: { ok: true, results: [{ title, url, description }, ...], moreResultsAvailable: bool } on success, or { ok: false, error: "message" } on failure.

var r = webSearch("MALDA programming language");           // Uses BRAVE_SEARCH_API_KEY or config
var r2 = webSearch("weather London", "your-brave-api-key"); // Explicit key
if (r.ok) { for (var i = 0; i < r.results.length; i++) print(r.results[i].title); }

13.5.3 HTTP auth token helpers

These helpers extract tokens from request-like objects used by HttpServer handlers.

var bearer = httpBearerToken(req); // Reads Authorization: Bearer <token>
var cookie = httpCookieToken(req, "app_session", "cookie-secret"); // Signed cookie token

var token = httpAuthToken(req, {
  "allowBearer": true,
  "allowCookie": true,
  "allowBody": true,
  "cookieName": "app_session",
  "cookieSecret": "cookie-secret",
  "bodyKey": "auth"
});

13.6 Array Utility Functions

var arr = [1, 2, 3, 4, 5];
var total = sum(arr);                       // 15
var avg = average(arr);                     // 3.0
var smallest = min(arr);                    // 1
var largest = max(arr);                     // 5
var total2 = arr.sum();                     // 15
var avg2 = arr.average();                   // 3.0
var smallest2 = arr.min();                  // 1
var largest2 = arr.max();                   // 5
var joined = join(arr, ", ");               // Join array elements into string (returns "1, 2, 3, 4, 5")
var reversed = reverse(arr);                // Return reversed array (returns [5, 4, 3, 2, 1])
var sorted = sort([3, 1, 4, 1, 5]);        // Sort array (returns [1, 1, 3, 4, 5])
var sortedDesc = sort([3, 1, 2], (a, b) => b - a);  // Custom compare: descending (interpreter and transpiled)
var hasValue = includes(arr, 3);            // Check if array contains value (returns true)

sort(array, compareFn?) — With one argument, returns a new array sorted with default comparison (numbers then strings). With an optional compareFn, the second argument must be a function (a, b) => number: return negative if a before b, 0 if equal, positive if a after b. Custom compare is supported in both interpreter and transpiled mode.

sum(array) returns the total of a numeric array. average(array) returns the arithmetic mean of a non-empty numeric array as a float. min(array) and max(array) return the smallest and largest numeric element in a non-empty array.

The same aggregate operations also support array-method syntax: array.sum(), array.average(), array.min(), and array.max().

13.6.1 CSV Export Helper

var rows = [
  {"name": "Alice", "score": 95},
  {"name": "Bob", "score": 88}
];

var csv1 = toCsv(rows, ["name", "score"]); // With explicit column order
var csv2 = toCsv(rows);                     // Infer columns from first row
var csv3 = toCsv(rows, ["name", "score"], {
  "delimiter": ";",
  "includeHeader": true,
  "quoteAll": false,
  "newline": "\n"
});

toCsv(rows, columns?, options?) converts an array of rows to CSV text. It escapes quotes and wraps cells when required (delimiter/newlines/quotes). Useful for reports and data export endpoints.

13.7 JSON Functions

var jsonStr = toJSON(obj);  // Convert object to JSON string
var obj = parseJSON('{"name":"Alice","age":30}');  // Parse JSON string to object

parseJSON parses arbitrary JSON into MALDA values. parseJson(jsonString, schemaName) parses JSON and validates it against a registered schema declaration, throwing on mismatch.

schema Answer {
    text: string;
    sources: string[];
}

var parsed = parseJson('{"text":"ok","sources":["a.md"]}', "Answer");
print(parsed.text);           // ok
print(parsed.sources[0]);       // a.md

Array field types use type[] syntax (e.g. string[], int[], or OtherSchema[]). Field types may also name another declared schema (nested object shapes are expanded for validation and typed prompts) or a declared sum type (tagged oneOf JSON). Optional fields append ? after the type. Unknown field type names and cyclic schema references raise an error when the schema is resolved.

13.7.1 validate(schema, value)

Checks a value that you already have against a schema, without parsing JSON. Unlike parseJson, a validation failure is not an exception: the result is always an object reporting the outcome.

The first argument is either the name of a registered schema or sum type, or an inline schema object. An unknown name raises Unknown schema 'Name'. On success, data is the original value — a tagged dict stays a dict (it is not coerced to a variant). Use await prompt … -> Intent when you need a variant for match.

schema Answer {
    text: string;
    sources: string[];
}

var candidate = dict { "text": "ok", "sources": ["a.md"] };

var checked = validate("Answer", candidate);
if (checked.ok) {
    print(checked.data.text);      // ok
} else {
    print("invalid: " + checked.error);
}
type Intent = Search(query) | Buy(sku, qty);
var tagged = dict { "tag": "Buy", "sku": "SKU-9", "qty": 2 };
var checkedIntent = validate("Intent", tagged);
if (checkedIntent.ok) {
    print(checkedIntent.data.tag);
}
type Intent = Search(query: string) | Buy(sku: string, qty: int);
var tagged = dict { "tag": "Buy", "sku": "SKU-9", "qty": "x" };
var checkedTyped = validate("Intent", tagged);
print(checkedTyped.ok);
Not to be confused with: memory.validate() on a GraphMemory instance, which checks graph integrity rather than a schema. The two share a name but are unrelated.

13.7.2 AI Pipeline Functions

These built-ins compose with the pipe operator (|>) for retrieval-augmented generation (RAG) and structured LLM output. See also 15. VectorDB (asRetriever) and Examples/Prompts/rag_pipeline.malda.

// Load text files matching a glob pattern (default directory: current)
var docs = loadDocuments("**/*.md", "docs/");

// Split long documents into overlapping chunks
var chunks = splitDocuments(docs, 512, 64);

// Index documents into a VectorDB (embeds content, preserves metadata)
indexInto(vdb, chunks);

// Format retrieved documents for prompt context
var context = query |> retriever.get |> formatRetrievedDocs;

// Execute a PromptInstance with the default or supplied LLM client
var response = await (promptInstance |> runPrompt(client));

// Stream tokens while the model responds
var seen = "";
function onTok(token) { seen = seen + token; }
var response = await runPrompt(promptInstance, client, { onToken: onTok });

// Stream model reasoning/thinking deltas (OpenRouter-compatible providers)
var reasoning = "";
function onReason(token) { reasoning = reasoning + token; }
var response = await runPrompt(promptInstance, client, { onReasoning: onReason });

// Attach runtime few-shot examples to a prompt instance
var p = classify("query") |> withExamples(dynamicExamples);

// Validate LLM JSON output against a schema
var parsed = response |> parseJson("Answer");

// Advanced composition: sequence + parallel branches
var pipeline = composePipe(formatRetrievedDocs, (ctx) => answerPrompt(q, ctx));
var context = question |> pipeline;

var branches = parallelRun(question, {
    context: (q) => q |> retriever.get,
    tags: classifyIntent
});
var merged = mergeRetrievedDocs(branches.context, branches.tags);
FunctionDescription
loadDocuments(pattern, dirPath?)Glob-matches files under dirPath (default "."); returns { content, metadata: { source } } per file
splitDocuments(docs, chunkSize, overlap?)Splits document content into overlapping chunks; copies metadata to each chunk
indexInto(vdb, docs)Embeds and adds each document to a VectorDB via its calculator; stores metadata with hits
formatRetrievedDocs(docs)Formats document arrays as [source: …] blocks joined for prompt context
composePipe(step1, step2, …)Composes 2+ callables (functions, lambdas, built-ins, prompts) left-to-right into a reusable function (input) => …. Awaits async steps. Pipe-friendly: input |> composePipe(f, g)
parallelRun(input, branches)RunnableParallel: feeds the same input to each named branch concurrently; returns an object/map of results. Use await when branches include async steps.
mergeRetrievedDocs(docArrays…)Flattens multiple Document[] arrays (e.g. from parallelRun) into one array; dedupes by source+chunk metadata or content
withExamples(prompt, examples, options?)Returns a copy of a PromptInstance with runtime few-shot examples. Pass { merge: true } to append after any static examples from the prompt declaration. Pipe-friendly.
runPrompt(prompt, client?, options?)Async: runs a PromptInstance through an LLM; returns response text. Optional options: { onToken: (token) => ... } for streamed content tokens; { onReasoning: (token) => ... } for streamed reasoning/thinking tokens. Both work in interpreted and transpiled mode with await and pipe steps.
parseJson(json, schemaName)Parses and validates JSON against a schema declaration; returns a typed object

13.8 File System Functions

How-to, failure styles, line ranges, capability tokens, and backend notes: 12. Input/Output. This section is the signature catalog.

var content = readFile("example.txt");                    // Read entire file
var lines = readFile("example.txt", 10, 20);              // Read lines 10-20 (1-indexed)
var fromLine = readFile("example.txt", 5);                // Read from line 5 to end
writeFile("output.txt", "Hello");                         // Write content to file
var exists = hasFile("example.txt");                      // Check if file exists
var dirExists = hasDirectory("mydir");                     // Check if directory exists
ensureDir("path/to/dir");                                  // Create directory and parents if missing
var files = listDirectory(".");                            // List directory contents

ensureDir(path) — Creates the directory and any missing parent directories. Does nothing if the directory already exists. Useful for creating ~/.malda/memory before saving assistant memory.

13.8.0 Embedded folders (embed:)

Compile with malda compile … --embed-folder <dir[=alias]> to pack a directory into the executable as assembly resources. At runtime, read those files with the virtual scheme embed:<alias>/<relative> — nothing is extracted to disk. Writes (writeFile, ensureDir, …) reject embed: paths.

if (io.hasEmbeddedFolder("secondbrain")) {
    var root = io.embeddedFolderRoot("secondbrain");   // "embed:secondbrain"
    var catalog = io.readFile(io.pathJoin(root, "brain.json"));
    var entries = io.listDirectory(root);
}

hasEmbeddedFolder(alias) returns whether that alias was embedded. embeddedFolderRoot(alias) returns embed:<alias>, or null when the alias is missing. Agent tools such as createReadFileTool, createGrepTool, and createListDirectoryTool accept an embed:<alias> working directory.

replaceInFile("file.txt", "old", "new", 3);               // Replace text in file (single replacement)
var edits = [{"oldText": "old1", "newText": "new1"}, {"oldText": "old2", "newText": "new2"}];
var result = editFile("file.txt", edits);                 // Apply multiple edits to file

13.8.1 Line, Binary, Delete, and PDF Text

FunctionReturnsBehavior
pdf.extractText(path, password?)stringExtracts text from a PDF using PdfPig (ContentOrderTextExtractor). Optional password for encrypted files. Throws when the path is missing or the PDF cannot be opened. Digital text only — scanned/image PDFs need OCR elsewhere. Prefer the namespaced spelling; the CallBuiltIn name is extractPdfText.
doc.extractText(path)stringExtracts body paragraph text from a Word .docx using the Open XML SDK. Throws when the path is missing, the file is not .docx, or the package cannot be opened. Legacy binary .doc is not supported. Prefer the namespaced spelling; the CallBuiltIn name is extractDocxText.
readTextFileLines(path)array of strings, or nullReads the file as UTF-8 and splits it into lines. Returns null when the file is missing or cannot be read.
deleteFile(path)booleanDeletes the file. Returns true when the file was deleted or was already absent; false on an empty path or an I/O failure.
insertAtLine(path, lineNumber, content, insertAfter?)booleanInserts content (which may span several lines) at a 1-indexed line. Returns false if the file does not exist.
readFileBase64(path)string, or nullReads the file as bytes and returns base64. Returns null when the file is missing.
writeFileBase64(path, base64Content)booleanDecodes base64 and writes the bytes. Returns false when the input is not valid base64 or the write fails.
var lines = readTextFileLines("notes.txt");
if (lines != null) {
    print("line count: " + lines.length);
}

insertAtLine("notes.txt", 1, "# Header");        // Insert before line 1
insertAtLine("notes.txt", 3, "appended", true);  // Insert after line 3

var encoded = readFileBase64("logo.png");
writeFileBase64("logo-copy.png", encoded);

deleteFile("scratch.txt");

var pdfText = pdf.extractText("manual.pdf");
// var unlocked = pdf.extractText("secret.pdf", "password");
var docText = doc.extractText("brief.docx");

For insertAtLine, a lineNumber of 0 or less inserts at the start of the file, and a value beyond the last line appends to the end. insertAfter defaults to false, meaning the content is inserted before the given line.

Failure style: readTextFileLines, deleteFile, insertAtLine, and the base64 helpers report ordinary failures through their return value (false or null) rather than by throwing. They only raise an error when called with the wrong number of arguments or the wrong argument types. Check the result rather than relying on try/catch. pdf.extractText and doc.extractText throw on missing files and parse failures.

insertAtLine is interpreter-only: it is not available in transpiled executables. The other file helpers, pdf.extractText / extractPdfText, and doc.extractText / extractDocxText are supported by the C# transpiler.

13.8.2 Searching Files: glob and grep

glob finds paths by pattern, and grep searches file contents. Both take a required argument first and then a series of optional, positional arguments.

glob(pattern, dirPath?, maxResults?, includeDirectories?, excludeDirs?, workingDirectory?)
var found = glob("**/*.malda", "Examples");
print(found.count);
print(found.truncated);

var first = found.items[0];
print(first.path + " (" + first.type + ")");
grep(pattern, filePath, useRegex?, caseInsensitive?, includeLineNumbers?, contextLines?, countOnly?, recursive?, workingDirectory?)
var matches = grep("function ", "Examples");
for (var m in matches) {
    print(m.filePath + ":" + m.lineNumber + " " + m.content);
}

var summary = grep("TODO", "Examples", false, true, true, 0, true);
print(summary.count + " hits in " + summary.filesSearched + " files");
Errors are returned as strings: when the path does not exist, or a regular expression is invalid, glob and grep return an error message instead of their normal result. Guard with typeOf(result) == "string" before treating the value as a collection.
var result = grep("needle", "does-not-exist");
if (typeOf(result) == "string") {
    print("search failed: " + result);
}

13.9 Git Functions

var status = gitStatus(".");                         // Get repository status
gitAdd(".", ".");                                     // Stage files
gitCommit(".", "Fix bug");                            // Create commit
var commits = gitLog(".", 10);                        // Get last 10 commits
var diff = gitDiff(".", null, false);                 // Get unstaged diff
var branches = gitBranch(".", "list");                // List all branches
gitBranch(".", "create", "feature-x");                // Create new branch
// Note: Branch deletion is disabled for safety
gitCheckout(".", "main", false);                      // Switch to branch
gitPush(".", "origin", "main");                       // Push to remote
gitPull(".", "origin", "main");                       // Pull from remote

13.10 Command Execution Functions

// Execute shell commands
        var result = runCommand("dotnet", ["build"], ".", 30000);  // Run dotnet build with 30s timeout
        // Returns: {exitCode: 0, stdout: "...", stderr: ""}

        var result = runCommand("npm", ["test"]);                  // Run npm test (no timeout)
        var result = runCommand("python", ["script.py"], "./scripts");  // Run with custom working directory

        // Result object structure:
        // - exitCode (integer): Process exit code (0 typically indicates success)
        // - stdout (string): Standard output from the command
        // - stderr (string): Standard error output from the command

13.11 MALDA Execution Functions

        // Execute MALDA code from file or string
        var result = runMALDA("example.malda");                    // Execute from file
        var result = runMALDA("print('Hello');");               // Execute from string
        var result = runMALDA("example.malda", "input data");      // Execute with stdin input

        // Result object structure:
        // - success (boolean): true if execution completed without errors
        // - output (string): Standard output from the program
        // - error (string): Parse error message if any, empty string otherwise
        // - runtimeError (string, optional): Runtime error message if any

        // Compile a .malda program to an executable (optional embed folder = CLI --embed-folder)
        var packed = compileMALDA("app.malda", "dist/app.exe", "transpile", "secondbrain");
        // embedFolder may be "path" or "path=alias"; result: { success, outputPath, error, errors }

13.10.1 getSymbols(sourceOrFilePath)

Parses MALDA code and extracts structured symbol information (classes, functions, actors, prompts) with line numbers and signatures. Accepts one string argument: a file path to a .malda file or MALDA source code. If the string looks like a file path (contains path separators or ends with .malda) and the file exists, the file is read and its content is parsed; otherwise the argument is treated as source code. Path traversal (.., ~) is rejected. Returns an object with classes, functions, actors, prompts, and parseErrors (all arrays). Each class/actor has name, line, column, members; each function has name, line, column, parameters, signature; each prompt has name, line, column, parameters, returnType?, signature. Parse errors have line, column, message.

var sym = getSymbols("Examples/OOP/classes_objects.malda");   // From file
var sym2 = getSymbols("function f() { } class C { }");        // From source
// sym.classes, sym.functions, sym.actors, sym.prompts, sym.parseErrors

13.10.2 getParseErrors(sourceOrFilePath)

Parses MALDA code and returns only parse errors (no execution). Accepts the same argument as getSymbols: file path or source string. Path resolution and security checks are the same. Returns { parseErrors: [{ line, column, message }, ...] }. Use to validate syntax without running or compiling.

var errs = getParseErrors("var x = ;");   // Invalid: empty rhs
// errs.parseErrors is non-empty with line, column, message
var ok = getParseErrors("var x = 1;");   // Valid: parseErrors is []
Command Execution Safety: The runCommand function includes comprehensive safety checks:

13.12 Spectre.Console Integration

MALDA exposes a global AnsiConsole object that wraps the .NET Spectre.Console library and provides rich console output:

// Markup (colors, bold, links, etc.)
AnsiConsole.markupLine("[green]Hello[/] [bold red]Spectre.Console[/]!");   // Appends a newline
AnsiConsole.markup("[dim]no newline, [/]");                                // Stays on the same line
AnsiConsole.markupLine("[cyan]rest of the line[/]");

// Tables
var rows = [
    {"Name": "Alice", "Score": 95},
    {"Name": "Bob", "Score": 88}
];
AnsiConsole.table(rows, "Scores");

// Panels (body and title accept markup)
AnsiConsole.panel("[bold]Important[/] message", "Info", "rounded");

// Trees
var treeData = {
    "root": "Project",
    "children": [
        {"label": "src"},
        {"label": "tests"}
    ]
};
AnsiConsole.tree("Project", treeData);

// Status
AnsiConsole.status("Processing...", () => {
    // Long-running work here
});

// Prompt (configuration object)
AnsiConsole.prompt({
    "type": "text",
    "message": "Enter your name"
});

// Progress - New callback-based syntax (recommended)
AnsiConsole.progress((ctx) => {
    ctx.addTask("Loading World Map", 100);
    
    while (!ctx.isFinished()) {
        ctx.increment("Loading World Map", 1.5);
        sleep(50);
    }
});

// Progress - Object-based syntax (legacy)
AnsiConsole.progress({
    "tasks": [
        {"name": "Task 1", "maxValue": 100}
    ],
    "action": (progressObj) => {
        var current = 0;
        while (current < 100) {
            current = current + 10;
            // Update progress by setting the value
            progressObj["Task 1"] = current;
            sleep(50);
        }
    }
});
Markup and Line Endings:
Progress API:
Where Spectre.Console Renders:

13.13 Date and Time Functions

var timestamp = now();                       // Get current timestamp in milliseconds (Unix epoch)
var formatted = formatDate(timestamp, "yyyy-MM-dd HH:mm:ss");  // Format timestamp (default: "yyyy-MM-dd HH:mm:ss")
var parsed = parseDate("2026-01-26 10:30:00");  // Parse date string to timestamp
var tomorrow = addDays(timestamp, 1);         // Add days to timestamp
var inHours = addHours(timestamp, 2);        // Add hours to timestamp
Date/Time Format:

13.14 Random Number Functions

var rand = math.random();                    // Random float between 0.0 and 1.0
var randInt = math.randomInt(1, 10);         // Random integer, 1 and 10 both included
var randFloat = math.randomFloat(0.0, 100.0); // Random float between 0.0 and 100.0

math.seed(7);                                // Pin the sequence for reproducible runs
var pinned = math.randomInt(1, 100);         // Always 39 after seed(7)
Reproducible Randomness:

13.15 Type Checking Functions

var isNum = isNumber(42);                    // Check if value is a number (integer or float)
var isStr = isString("hello");               // Check if value is a string
var isArr = isArray([1, 2, 3]);              // Check if value is an array
var isObj = isObject({name: "Alice"});       // Check if value is an object
var type = typeOf(42);                       // Canonical tag ("int", "string", "dict", "object", "variant", "task", "null", ...)
var isInt = isTag(42, "int");                 // true; isTag also accepts legacy names like "integer" during deprecation

13.16 Encoding and Decoding Functions

var encoded = base64Encode("Hello World");    // Base64 encode string
var decoded = base64Decode(encoded);         // Base64 decode string
var urlEncoded = urlEncode("Hello World");   // URL encode string (returns "Hello%20World")
var urlDecoded = urlDecode(urlEncoded);      // URL decode string

13.17 Hash Functions

var md5Hash = md5("Hello World");             // Calculate MD5 hash (returns hex string)
var sha256Hash = sha256("Hello World");      // Calculate SHA-256 hash (returns hex string)
Hash Functions:

13.16.1 Password and JWT Security Functions

var passwordHash = hashPassword("my-password");              // PBKDF2-SHA256 hash
var isValid = verifyPassword("my-password", passwordHash);   // true/false

var claims = {"sub": "user-123", "role": "admin"};
var token = createJwt(claims, "my-jwt-secret", 3600);        // expires in 3600s
var token2 = createJwt(claims, "my-jwt-secret", {
  "expiresInSeconds": 3600,
  "issuer": "malda-core",
  "audience": "malda-apps",
  "notBeforeSeconds": 0
});
var verifiedClaims = verifyJwt(token2, "my-jwt-secret", {
  "issuer": "malda-core",
  "audience": "malda-apps"
});
print(verifiedClaims.sub);

var csrfToken = generateCsrfToken("csrf-secret", 3600);
var csrfOk = verifyCsrfToken(csrfToken, "csrf-secret");      // true/false

var setCookieHeader = createSecureCookie("session", "user-123", "cookie-secret");
// send with res.header("Set-Cookie", setCookieHeader) or use res.cookie(...)
var cookieValue = split(split(setCookieHeader, ";")[0], "=")[1];
var session = readSecureCookie(urlDecode(cookieValue), "cookie-secret");
Security Function Notes:

13.16.1a Background jobs (lightweight queue)

Short async units (email, webhooks) use a SQLite queue at ./.malda/jobs.db. This is separate from durable workflow processes.

var jobId = enqueueJob("mail", {"to": "user@example.com"}, {"maxAttempts": 3});
var job = claimJob("mail", "worker-1");
if (job != null) {
    // ... do work with job.payload ...
    completeJob(job.id, {"sent": true});
    // or: failJob(job.id, "SMTP timeout", true);
}
var open = listJobs("mail", "pending", 20);
var one = getJob(jobId);
Job helpers:

13.16.2 Request auth context (req.auth)

Both HttpServer and RestServer expose the same req.auth surface on each request:

function requireAuth(req, res, next) {
    req.auth.authenticateBearerJwt(getEnv("MALDA_JWT_SECRET"));
    next();
}

server.use(requireAuth, { "except": ["/api/health", "/metrics"] });

13.18 Range Generation

var range1 = range(5);                        // Generate [0, 1, 2, 3, 4]
var range2 = range(1, 10);                   // Generate [1, 2, 3, 4, 5, 6, 7, 8, 9]
var range3 = range(0, 10, 2);                // Generate [0, 2, 4, 6, 8] (step of 2)
var range4 = range(10, 0, -1);               // Generate [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] (negative step)

13.19 Error Handling Functions

exit(0);                                      // Exit program with exit code 0 (success)
exit(1);                                      // Exit program with exit code 1 (error)
error("Something went wrong");                // Throw runtime error with message
assert(x > 0, "x must be positive");          // Assert condition is true, throw error if false
assert(isValid, "Validation failed");        // Assert without custom message
Error Handling:

13.19.1 result and option

Prefer these modules when a function should report success or absence without throwing. They return variants with tags Ok/Err and Some/None — the same shape as a type Result = Ok(value) | Err(message) declaration, but you do not need to declare the type. The module names are lowercase (result, option); a user-declared type Result is a different name.

Use try/catch for unexpected failures (see 8. Control Structures). Use result/option for expected outcomes in the return value.

function parseAge(raw) {
    var n = toIntOrNull(raw);
    if (n == null) {
        return result.err("not an int");
    }
    return result.ok(n);
}

print(result.unwrapOr(parseAge("12"), 0));
print(result.isErr(parseAge("x")));

var present = option.some("hi");
var missing = option.none();
print(option.unwrapOr(present, "no"));
print(option.isNone(missing));
function parseAge(raw) {
    var n = toIntOrNull(raw);
    if (n == null) {
        return result.err("not an int");
    }
    return result.ok(n);
}
function doubleAge(n) {
    return result.ok(n * 2);
}
print(result.unwrapOr(parseAge("12") |> result.andThen(doubleAge), 0));
print(result.isErr(parseAge("x") |> result.andThen(doubleAge)));

Do not treat type hints (var n: int = …) as runtime validation. For JSON-shaped payloads use schema and validate(). Tutorial: errors, Result/Option, and schema validate.

13.19.2 grounded.wrap

Retrieval citations (GraphMemory, files, tools) are not a match-visible value kind. Wrap a payload so provenance is a dict you can read:

var g = grounded.wrap("the sky is blue", [
    { "source": "wiki", "id": "p1", "span": "12-40" }
]);
print(g.value);
print(g.sourced);
print(g.citations[0].source);

13.19.3 cap.fileRead

@effects("io") is a name allow-list. Pass an unforgeable token into a tool so the model cannot invent a path. Tokens are sealed host objects, not dicts — JSON and object literals cannot rehydrate one.

var notes = cap.fileRead("notes.md");
print(notes.kind);
print(cap.is(notes, "fileRead"));
var forged = false;
try {
    cap.read({ "kind": "fileRead", "path": "notes.md" });
} catch (e) {
    forged = true;
}
print(forged);

13.20 Structured Task Planning

decomposeTask, executePlan, and createSubmitPlanTool live in 18. Agent Orchestration (§ 18.13). runProgram runs a closed api / program(ApiName) value with no further LLM calls — see 10. Prompts (§ 10.8 Closed APIs and Deterministic Programs).

13.21 Tool Creation Functions

Agent tool factories (createReadFileTool, createWriteFileTool, createReplaceInFileTool, createEditFileTool, createInsertAtLineTool, createGrepTool, createListDirectoryTool, createAskUserTool, createWebSearchTool, createGitStatusTool, createGitAddTool, createGitCommitTool, createGitLogTool, createGitDiffTool, createGitBranchTool, createGitCheckoutTool, createGitPushTool, createGitPullTool, createRunCommandTool, createRunMALDATool, createCompileMALDATool, createGetSymbolsTool, createGetParseErrorsTool, createSubmitPlanTool, createGlobTool, createCreateMcpAgentScriptTool) live in 18. Agent Orchestration (§ 18.6). createNativeCallback wraps a MALDA function as a .NET delegate — see 30. .NET Interop.

13.22 Durable Workflow Operations

Runtime, query, and control helpers (startWorkflow, getWorkflowStatus, getWorkflow, getWorkflowSteps, getWorkflowEvents, getWorkflowMetrics, listWorkflows, listWorkflowDeadLetters, requeueDeadLetter, runWorkflowInstance) live in 22. Durable Workflows.

13.23 Agent Runtime Logging

Diagnostic helpers (enableAgentVerboseLogging, setAgentVerbosePhase, setAgentStatusBanner, reportRalphStatus) live in 18. Agent Orchestration (§ 18.5 and 18.18 Ralph Wiggum). They affect presentation only and never change an agent's result.

13.24 Web UI Functions

Server component helpers (renderTemplate, componentFragment, componentLiveEmit, componentState*, onAgentProgress, clearAgentProgress) and ui.* controls live in 24. Web UI Server Components. Start from 23. Web UI Overview if you are choosing a UI model.

13.25 Optional packs (not in core)

Core BuiltInRegistry lists only open-source core symbols. Domain-specific builtins may ship in separately distributed packs; load them with loadNativeModule(...) and ship any required assemblies beside your app. Core does not auto-register pack globals.

See Also