Referencia
Índice de builtins
Un mapa categorizado de los builtins. Las firmas completas viven en cada página de tema; los centrales están doctested acá para que esta referencia no driftee.
-- Doc reference: a few core builtins, doctested so the reference can't drift.
intent: "doc reference: core builtins"
print("upper(\"hi\") = " + upper("hi") + ", join([a,b],\"-\") = " + join(["a", "b"], "-"))
test "collections"
assert_eq(length([1, 2, 3]), 3)
assert(contains([1, 2, 3], 2))
assert_eq(slice([1, 2, 3, 4], 1, 3), [2, 3]) -- Python-style end-exclusive
assert_eq(keys({"a": 1, "b": 2}), ["a", "b"])
assert_eq(values({"a": 1, "b": 2}), [1, 2])
test "text"
assert_eq(upper("hi"), "HI")
assert_eq(trim(" x "), "x")
assert_eq(split("a,b,c", ","), ["a", "b", "c"])
assert_eq(join(["a", "b"], "-"), "a-b")
assert(starts_with("hello", "he"))
test "intentional ops"
assert_eq(apply((n) => n * 2, [1, 2, 3]), [2, 4, 6])
assert_eq(where([1, 2, 3, 4], (n) => n > 2), [3, 4])
assert_eq(reduce([1, 2, 3], (a, b) => a + b, 0), 6)
test "intentional ops accept both orders (fn-first and list-first)"
assert_eq(apply([1, 2, 3], (n) => n * 2), [2, 4, 6]) -- list-first also works
assert_eq(where((n) => n > 2, [1, 2, 3, 4]), [3, 4]) -- fn-first also works
assert_eq(reduce((a, b) => a + b, [1, 2, 3], 10), 16) -- extra args stay at the end
test "unique and index_of"
assert_eq(unique([3, 1, 3, 2, 1]), [3, 1, 2]) -- first-appearance order
assert_eq(index_of([10, 20, 30], 20), 1) -- by item
assert_eq(index_of([1, 2, 3], (n) => n > 1), 1) -- by predicate
assert_eq(index_of([1, 2], 9), nothing) -- absent → nothing, not -1
assert_eq(index_of("héllo", "llo"), 2) -- on text: the character position
test "reverse and split(text, \"\") (engine v0.6.20+)"
assert_eq(reverse([1, 2, 3]), [3, 2, 1]) -- a NEW list; the original is untouched
assert_eq(reverse("abc"), "cba") -- text too (by Unicode scalar)
assert_eq(split("abc", ""), ["a", "b", "c"]) -- empty separator → the characters
assert_eq(split("", ""), [])
test "renamed in v0.6.29: the new names (the old ones are deprecated aliases until v1.0)"
assert_eq(replace("a-b-c", "-", "+"), "a+b+c") -- was replace_text
assert_eq(regex_find_all("a1b2", "[0-9]"), ["1", "2"]) -- was find_all
assert_eq(regex_replace("a1b2", "[0-9]", "#"), "a#b#") -- was replace_re
assert_eq(fold_text("Continúa"), "continua") -- was fold
assert_eq(identity(2), array([[1, 0], [0, 1]])) -- was eye
-- regex_capture (was capture) is ALWAYS a list, or nothing
assert_eq(regex_capture("2026-09", "([0-9]+)-([0-9]+)"), ["2026", "09"]) -- the groups
assert_eq(regex_capture("hello world", "w[a-z]+"), ["world"]) -- no groups → [match]
assert_eq(regex_capture("abc", "[0-9]+"), nothing)
-- hmac (was hmac_sha256) returns BYTES; hmac_sha256 returned hex text
let mac be hmac("data", "key")
assert_eq(type_of(mac), "bytes")
assert_eq(hex(mac), "0x" + decode(mac, "hex"))
test "maps and lists: get, items, merge, remove, insert, sort desc (v0.6.29+)"
assert_eq(get({"a": 1}, "b", 0), 0) -- Python's d.get(k, default)
assert_eq(get({"a": 1}, "b"), nothing)
assert_eq(get([1, 2, 3], -1), 3) -- lists too; negative from the end
assert_eq(items({"x": 1}), [{"key": "x", "value": 1}])
assert_eq(merge({"a": 1, "b": 2}, {"b": 3, "c": 4}), {"a": 1, "b": 3, "c": 4}) -- rightmost wins
assert_eq(remove({"a": 1, "b": 2}, "a"), {"b": 2}) -- a NEW map
assert_eq(insert([1, 2, 3], 1, 9), [1, 9, 2, 3])
assert_eq(sort([3, 1, 2], desc = true), [3, 2, 1])
assert_eq(sort_by([{"n": 1}, {"n": 2}], (r) => r.n, desc = true), [{"n": 2}, {"n": 1}])
test "type predicates and exact integers (v0.6.29+)"
assert(is_integer(1) and not is_integer(1.0))
assert(is_text("a") and is_list([]) and is_map({}))
assert_eq(int("ff", base = 16), 255) -- the base goes by name
assert_eq(int("abc", fallback = 7), 7) -- so does the fallback
assert_error(() => int("ff", 16)) -- 2..36 in second place: ambiguous → error
assert_eq(hex(7960), "0x1f18")
assert_eq(int("0x1f18"), 7960)
assert_eq(7 // 2, 3) -- floor division
assert_eq(-2 ** 2, -4) -- ** binds tighter than unary minus
test "strict arity (v0.6.29+): extra or missing arguments are errors"
task one(a)
give a
task two(a, b)
give a
assert_error(() => append([1], 2, 3)) -- was: the 3 silently dropped
assert_error(() => one(1, 2))
assert_error(() => two(1)) -- was: b arrived as nothing
test "text + nothing is an error; fmt is strict; a template hole takes any value"
assert_eq("n=" + 1, "n=1") -- text + number still joins
assert_error(() => "n=" + nothing)
assert_error(() => "xs=" + [1, 2])
assert_eq(`xs={[1, 2]} n={nothing}`, "xs=[1, 2] n=nothing")
assert_error(() => fmt("{a} {b}", {"a": 1})) -- a {name} without a value
assert_eq(fmt("^[0-9]{3}-{n}$", {"n": 1}), "^[0-9]{3}-1$") -- not a name → stays literal
assert_eq(text(["1", 1]), "[\"1\", 1]") -- text inside a list is shown quoted
test "lists and maps are values (v0.6.29+): a task gives back what it changes"
let xs be [1, 2]
let ys be xs
set ys[0] to 9
assert_eq(xs, [1, 2]) -- only ys changed
task mark(cfg)
set cfg["seen"] to true
give cfg
let c be {"seen": false}
mark(c)
assert_eq(c["seen"], false) -- the task changed its own copy
set c to mark(c)
assert_eq(c["seen"], true) -- the change leaves with `give`
test "tables and statistics (v0.6.29+)"
let rows be [{"region": "n", "amount": 1}, {"region": "s", "amount": 2}, {"region": "n", "amount": 3}]
let groups be group_by(rows, "region") -- [{key, items}], first-appearance order
assert_eq(groups[0].key, "n")
assert_eq(length(groups[0].items), 2)
assert_eq(summarize(rows, "region", {"total": sum_of("amount")}), [{"region": "n", "total": 4}, {"region": "s", "total": 2}])
assert_eq(count_by(["x", "y", "x"]), [{"key": "x", "count": 2}, {"key": "y", "count": 1}])
assert_eq(mean([1, nothing, 3]), 2.0) -- reductions skip nothing
assert(std([1, 2, 3, 4]) > std([1, 2, 3, 4], ddof = 0)) -- sample by default, like pandas
test "dates, seeded randomness, Parquet and JSON Lines (v0.6.29+)"
assert_eq(add_days(date("2026-09-24"), 7), date("2026-10-01"))
assert_eq(type_of(datetime("2026-09-24T10:00:00Z")), "datetime")
assert_eq(in_units(duration(hours = 1, minutes = 30), "minutes"), 90.0)
assert_eq(rng(42)(), 0.7739560485559633) -- numpy.random.default_rng(42).random()
let rows be [{"a": 1, "day": date("2026-09-24")}]
assert_eq(parquet_read(parquet_write(rows)), rows)
assert_eq(jsonl_decode(jsonl_encode([{"a": 1}])), [{"a": 1}])
test "EVM names (v0.6.29+): pure helpers under the evm_/abi_ prefixes"
assert_eq(abi_event_topic("Transfer(address,address,uint256)"), "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
assert_eq(evm_create_address("0x0000000000000000000000000000000000000001", 0), "0x522B3294E6d06aA25Ad0f1B8891242E335D3B459")
test "steps() counts executed statements — deterministic, no capability (engine v0.6.20+)"
let before be steps()
each i in range(100)
let x be i
assert(steps() - before > 100)
test "program & subprocess: args() and self_path() (no capability)"
assert_eq(type_of(args()), "list") -- the program's argv (empty under `synsema test`)
assert_eq(type_of(self_path()), "text") -- this executable's path
assert(length(self_path()) > 0)Renombrados en v0.6.29§
v0.6.29 fijó los nombres una sola vez, antes de v1.0. El nombre viejo es un alias deprecado: sigue corriendo, un programa que lo usa imprime un único aviso en stderr al cargar (también para un módulo cargado con use, v0.6.30+), synsema check marca cada uso, y se va en v1.0. Escribí el nombre nuevo — y leé la columna "significado", porque tres de ellos no devuelven lo mismo:
| Viejo | Nuevo | Significado |
|---|---|---|
replace_text | replace | igual |
find_all | regex_find_all | igual |
replace_re | regex_replace | igual |
capture | regex_capture | cambió: siempre una lista — los grupos, o [match] cuando el patrón no tiene — o nothing. El capture viejo devolvía el texto del match pelado sin grupos, y lo sigue haciendo |
fold | fold_text | igual (minúsculas + sin acentos; no es el casefold de Python) |
eye | identity | igual (arrays numéricos) |
hmac_sha256(data, key) → texto hex | hmac(data, key, algo?) → bytes | cambió: hex(mac) lo muestra como "0x…", decode(mac, "hex") da el hex pelado de antes |
eth_rpc, eth_nonce, eth_balance, eth_gas_price, eth_chain_id, eth_estimate_gas, eth_call, eth_fee_history | evm_rpc, evm_nonce, evm_balance, evm_gas_price, evm_chain_id, evm_estimate_gas, evm_call, evm_fee_history | igual. Los nombres de método JSON-RPC que le pasás a evm_rpc siguen siendo "eth_call", "eth_getLogs", … |
eth_send_raw, eth_receipt, eth_wait_receipt, eth_address | evm_send, evm_receipt, evm_wait, evm_address | igual |
tx_eip1559, tx_eip1559_raw | evm_tx, evm_tx_raw | igual; crear un contrato es el nuevo evm_tx_create, y evm_tx sin to es un error que apunta ahí |
solana_message (construye) | solana_tx(params) | el nombre solana_tx cambió de significado: ahora CONSTRUYE el mensaje |
solana_tx(message, signatures) (ensambla) | solana_tx_raw(message, signatures) | la llamada vieja de dos argumentos a solana_tx es un error que apunta a solana_tx_raw |
solana_confirm | solana_wait | igual |
algorand_tx_encode (bytes a firmar) | algorand_tx(txn) | el nombre algorand_tx cambió de significado: ahora devuelve los bytes a firmar |
algorand_tx(txn, sig) (firmada) | algorand_tx_raw(txn, sig) | la llamada vieja de dos argumentos a algorand_tx es un error que apunta a algorand_tx_raw |
algo_address | algorand_address | igual |
Sin cambios a propósito: matches, find_first, read_file(path, line, limit). Blockchain sigue <familia>_<acción> (Bitcoin ya lo hacía: btc_tx/btc_tx_raw/btc_send/btc_wait).
Reglas que cumple todo builtin (v0.6.29+)§
- Aridad estricta. Un builtin que recibe más de su máximo es un error (`append() takes at most 2
arguments, got 3); antes, los sobrantes se descartaban en silencio (trim(s, "x") ignoraba el "x"). Una task o lambda que llamás con un argumento de menos (task 'f' is missing argument 'b') o de más (task 'f' takes 1 argument, got 3) también es un error. Los builtins toman los argumentos por posición, salvo las formas con nombre documentadas (sort/sort_by desc = true, int base = / fallback =, std/var ddof =, recall(from = …), random_normal(g, mean =, std =), duration(hours = …), …). Los callbacks que llama un builtin o el host (apply, where, reduce`, handlers de rutas, cron) siguen recibiendo lo que reciben.
- Las listas y los maps son valores. Un builtin nunca cambia la lista o el map que le pasás:
append, insert, merge, remove, sort, reverse devuelven uno nuevo (y set xs to append(xs, v) es O(1): escribe en el lugar cuando nadie más tiene la lista). Una task que hace set dentro de un map que recibió cambia su propia copia — devolvelo con give. El estado compartido sigue siendo explícito: blackboard, memoria, bus, state_* — ver Multi-agente y Memoria y estado.
- Texto +
nothing/lista/map/bytes/task es un error (`Cannot add text and nothing — convert it
on purpose); texto + número/bool sigue uniendo. Un hueco de template toma cualquier valor: xs={xs} n={nothing} → xs=[1, 2] n=nothing. join(xs, sep)` rechaza los mismos ítems.
fmtes estricto: un{nombre}sin valor en el map es un error ({{nombre}}para una llave
literal); las llaves que no rodean un nombre — JSON, CSS, cuantificadores de regex como {3} — quedan literales.
- Dentro de una lista o un map, el texto se muestra entre comillas:
print(["1", 1])→
["1", 1]; un print("x") de primer nivel no cambia.
Por categoría§
- Núcleo / conversión:
print,eprint(v0.6.42+: comoprint, a stderr),exit(code?)(v0.6.42+: termina unsynsema runcon ese código;tryno lo atrapa; v0.6.45+: también un programaserveantes de que escuche — ver CLI),length,text,number(siempre un float; un texto entero más allá de ±2⁵³ es un error que nombraint),int(x)(exacto, de cualquier tamaño;int(text, base = 16),int(x, fallback = 0)— un entero 2..36 como segundo argumento posicional es un error, porque a un ojo de Python le suena a base y para el engine es un fallback),hex(x)(un entero →"0x1f18", bytes → cada byte),decimal,float,type_of(también"date","datetime","duration"), predicadosis_integer(is_integer(1.0)esfalse),is_text,is_list,is_map(v0.6.29+),is_bytes,is_decimal,is_complex,is_array,is_missing. - Colecciones:
length,contains,slice,keys,values,items(v0.6.29+:[{key, value}, …]),get(map, key, default?)(v0.6.29+: eld.getde Python; tambiénget(lista, i, default)),merge(a, b, …)(v0.6.29+: un map nuevo, gana el valor de más a la derecha),remove(map, key)(v0.6.29+: un map nuevo),append,insert(lista, i, item)(v0.6.29+; fuera de rango es un error, Python recorta),range(solo argumentos enteros),sort(lista, desc = true)ysort_by(lista, key, desc = true)(un orden total y estable —nothingy NaN al final, tipos mezclados no comparables un error),apply,where,reduce,find_first,every,some,collect,count_where,flatten,chunk(un tamaño entero),zip_with,reverse(engine v0.6.20+: una lista nueva en orden inverso; en texto, los caracteres invertidos),unique(dedupe, orden de primera aparición, igualdad estructural),index_of(índice base 0 del ítem o del primer match del predicado; ausente →nothing, no -1; en texto, la posición en caracteres, v0.6.29+).enumerate(lista)→[{index, item}, …]para loops indexados (lenguaje y templates). Operadores (v0.6.29+):x in xs/x not in xs, índices negativosxs[-1], un carácters[0]; un índice tiene que ser entero (xs[1.7]es un error,xs[1.0]está bien). Las ops intencionales que toman un callable aceptan los dos órdenes —apply(fn, lista)yapply(lista, fn)se leen igual de bien; dos tasks o dos listas donde se espera una y una es un error explícito. v0.6.46+:enumeratetambién toma un array y recorre su primer eje (cadaitemes un número en 1-D, la fila en 2-D o más; un array 0-d es un error). - Texto:
upper,lower,fold_text(erafold),trim,starts_with,ends_with,split(split(t, "")→ los caracteres, v0.6.20+),join,replace(erareplace_text),index_of,min/maxsobre texto,text,fmt(estricto, ver arriba),strip_ansi(engine v0.6.8+: salida de terminal → texto plano; escapes CSI/OSC/charset y bytes de control fuera, los redibujos con\rconservan el último cuadro). - Regex (puras):
matches(match completo),regex_find_all(erafind_all),regex_capture(eracapture— siempre una lista onothing),regex_replace(erareplace_re). - Números / matemática:
+ - * / %y la división entera//(exacta para enteros de cualquier tamaño;//y%de floats son los de CPython),-2 2es-4,|>pasa el valor como primer argumento de un paso que es una llamada; literales0x1f18,0o17,0b101,1_000,1e-9; constantespi/tau/e/inf/nan;abs,sign,min,max,clamp,sqrt,cbrt,hypot,pow,exp,ln,log10,log2,log_base,floor,ceil,round,trunc(enteros exactos, también desde un decimal),round_to(el valor binario real de un float, como Python:round_to(2.675, 2)es2.67; los decimales redondean al par),sin/cos/tan/asin/acos/atan/atan2,radians/degrees,sinh/cosh/tanh/asinh/acosh/atanh,gcd,lcm,factorial,is_nan/is_infinite/is_finite,gamma/lgamma/erf/erfc/beta;decimal(precisión arbitraria desde v0.6.29;decimal("1.5e-3")con exponente, v0.6.30+; comparar un decimal con un float es un error),complex/real/imag/conj/arg; arraysarray,arange,linspace,zeros,ones,identity(eraeye),full,reshape,shape,ndim,size,transpose,trace,dot(solo dos vectores, v0.6.29+),norm,matmul(matrices),solve,det,inv,eig,svd,concat,stack,cumsum,diff,argmin,argmax;bytes_to_int,int_to_bytes,int_to_bytes_le— ver Bytes, matemática y arrays. - Bytes / cripto:
bytes,decode(encodings:utf8,hex,base64,base64url,base58,base32),sha256,sha512,hmac(data, key, algo?)→ bytes (erahmac_sha256, que devolvía texto hex;data/keytexto, bytes — crudos desde v0.6.44 — o un secret),verify_hmac,constant_time_eq,basic(user, secret)/oauth_basic(client_id, secret)(v0.6.44+, HTTP Basic como secret),xor_bytes(a, b)(v0.6.44+, mismo largo); bits sobre enteros de 64 bits (v0.6.44+):bit_and,bit_or,bit_xor,bit_not,shl,shr; ECDH / HKDF / AES-GCM (engine v0.6.20+ — ver Bytes, matemática y arrays):ecdh_keypair(curve)(require random),ecdh_shared_secret,ecdh_public(private, curve)(v0.6.42+), curvas"P-256","P-521"y"X25519"(v0.6.42+),hkdf_sha256,aes_gcm_encrypt,aes_gcm_decrypt. - Web Push (engine v0.6.15+ — ver Tu app en el teléfono):
push_vapid_keys()→{public, private}(require random; la privada vuelve comosecretcon labelvapid_private);push_send(subscription, payload, opts)→{status, ok, gone, retry_after, body}(require net("<host del endpoint>")—fcm.googleapis.comyjmt17.google.com(Chrome usa cualquiera),*.notify.windows.com,updates.push.services.mozilla.com,web.push.apple.com;opts.vapid = {public, private: secret, subject}obligatorio,ttl,urgency,topic,timeout; payload texto / map→JSON / bytes /nothing, ≤ 3993 bytes;gonecon 404/410). RFC 8291aes128gcm+ VAPID RFC 8292, sin proveedor; no está en el perfil wasm. - Web auth (engine v0.5.5+ — ver Login y sesiones):
password_hash,password_verify,jwt_sign(HS256; RS256/ES256 con un secret PEM víaopts.alg/opts.kid, v0.6.20+),jwt_verify(HS256),rsa_sign_sha256/rsa_verify_sha256,ecdsa_p256_sign/ecdsa_p256_verify(v0.6.20+),totp,totp_verify(puros);random_bytes,token(require random); respuestaswith_header,set_cookie,clear_cookie;request.cookies; auth task de 2 parámetros. - Identidad de agentes y auth (engine v0.5.6+ — ver Identidad de agentes): tokens de capacidad
captoken_mint,captoken_attenuate(offline, sin clave),captoken_verify,captoken_allows(puros); requests firmadashttp_sign(require sign("CLAVE")+ auditoría) yhttp_signature_verify(puro,opts.algobligatorio); OIDC de tercerosoidc_verify(iss+audobligatorios; el JWKS necesitarequire net(host));mtls_identity(cert, key, opts?)con alcance poropts.hosts(require file.read); medición por identidad:spend_total(unidad, identidad?), rate limits por identidad ySYNSEMA_SPEND_CEILING_PER_IDENTITY="agente=UNIDAD:tope"(cualquier unidad — ninguna moneda privilegiada); descubrimiento en/.well-known/synsema-auth. - Passkeys,
did:key, documentos firmados, recibos (engine v0.6.28+ — ver Identidad de agentes):webauthn_register/webauthn_verify(puros; la attestation se ignora a propósito;nothingante cualquier falla);canonical_json(RFC 8785);did_key_encode/did_key_decode/did_key_document;document_sign/document_verify(W3C Data Integrity,eddsa-jcs-2022conrequire sign("KEY"),ecdsa-jcs-2019);receipt/receipt_verify(una Verifiable Credential derivada de la auditoría);jwt_signconalg: "EdDSA"yjwt_verify(token, {"did": …}); la Agent Card firmada en/.well-known/agent-card.json(SYNSEMA_IDENTITY_KEY). - Tiempo:
now,sleep(los únicos dos que leen el reloj y necesitanrequire time);format_time,parse_time,date_parts(puros desde v0.6.29). - Fechas, instantes y duraciones (v0.6.29+, puros — ver Tiempo y random): los tipos
date,datetime(una zona IANA, correcta ante el cambio de hora, o un offset fijo como+05:30) yduration, con aritmética y comparación;add_days,add_months,truncate,date_range,to_timezone,timestamp,in_units,parse_date,parse_datetime(%Zacepta soloUTC/GMTdesde v0.6.30 — usá%zo pasá la zona; un formato de solo fecha es medianoche). JSON y CSV los escriben como ISO 8601. - Random:
random,random_int(random,random_bytesytokennecesitanrequire random— entropía del SO). Con semilla, puros (v0.6.29+, los mismos números quedefault_rngde numpy, permitidos bajo--deterministic):rng(seed)→ un generadorg(g()/random(g)),random_int(g, lo, hi),random_normal(g, mean =, std =),shuffle(g, xs),choice(g, xs),sample(g, xs, n),rng_spawn(g, n)— ver Tiempo y random. - Cron:
cron_every,cron_after,cron_cancel,cron_list,cron_status;cron_every(expr, task, {"tz": "America/Santiago"})corre en una zona IANA a través de los cambios de hora (v0.6.30+) — ver Cron. - JSON:
json_encode,json_decode;json_for_script(el mismo JSON con</>/&escapados\u00XX— la forma segura de incrustar datos en un<script>inline); XML / TOML (v0.6.20+):xml_parse(convención xmltodict),toml_parse,toml_encode— ver JSON, XML y TOML. v0.6.46+:json_encode/jsonl_encode/json_for_script(ycsv_encode) de unsecretson un error que nombra dónde está — antes salía"[redacted]"(ver Secretos). - JSON Lines, CSV, Parquet (puros; el I/O de archivos es
read_file/read_file_bytes/write_filecon su propia capacidad):jsonl_encode,jsonl_decode(v0.6.29+);json_decode(text, allow_nan = true)lee losNaN/Infinityque escribejson_encode(un error por defecto), yjson_encoderechaza una task o un generador dentro del valor (v0.6.30+);csv_parse(text, opts?)({"types": {col: "int"|"float"|"decimal"|"text"|"bool"|"date"|"datetime"}},{"missing": ["NA", …]}; un campo vacío esnothingdesde v0.6.29),csv_encode(rows, opts?)({"missing": "NA"},{"escape_formulas": true});parquet_read(bytes, opts?)({"max_cells": n, "max_bytes": n}),parquet_write(rows, opts?)({"compression": "snappy"|"zstd"|"gzip"|"lz4"|"none"}; escribe el schema de Arrow, así pandas y polars leen las duraciones y los datetimes con zona con su tipo, v0.6.30+; no está en el build wasm); v0.6.45+:parquet_read(bytes, {"columns": […], "row_groups": […], "limit": n})lee una parte (los límites cuentan solo lo leído) yparquet_info(bytes)→{rows, columns: [{name, type}], row_groups: [{rows, bytes}]}sin leer los datos (solo nativo);gzip(data)→ bytes (determinista: sin nombre ni hora en el header) ygunzip(bytes, {"max_bytes": n})→ bytes (miembros concatenados; por defecto rechaza más que el mayor entre 256 MiB y 64 × la entrada —decode(…, "utf8")para texto) — ver JSON, XML y TOML y Análisis de datos. v0.6.46+:parquet_scan(path, opts?)lee una parte directo del disco — el footer y sólo las páginas pedidas (columns,row_groups,limit, los mismos chequeos queparquet_read); necesitafile.ready es una entrada de linaje con la ruta (ver Análisis de datos). - Tablas — análisis de datos (v0.6.29+, puros; una tabla es una lista de maps — ver Análisis de datos):
summarize(rows, by, aggs)con los agregadossum_of,mean_of,min_of,max_of,median_of,quantile_of,first_of,n_unique_of,count();group_by(rows, key)→[{key, items}](cambió en v0.6.29: devolvía un map con claves de texto);count_by;join(left, right, on, how?)(inner/left/right/outer/semi/anti— con 2 argumentosjoinsigue siendo el join de texto);pivot(rows, index, columns, values, agg?); datos faltantesis_missing,fill_missing,drop_missing,fill_nan,count(valores presentes),count_missing. Un nombre de columna que no tiene ninguna fila es un error. - Estadística:
sum,mean,median,mode,quantile(values, q),percentile,histogram,stdyvar(estadísticos muestrales desde v0.6.29,ddof = 1como pandas —std(xs, ddof = 0)para la cifra poblacional;synsema checkmarca cada llamada hasta v1.0),corr,cov,lstsq,polyfit,polyval. Toda reducción salteanothingy propaga NaN;axis =en arrays. - Linaje (v0.6.29+): el engine registra cada entrada que lee el programa — archivos, HTTP, SQL/Mongo/Redis,
recall, nodos de cadenas, procesos, respuestas del modelo — con su sha256;lineage()la lista yreceipt()la publica comoinputs— ver Observabilidad e Identidad de agentes. Desde v0.6.46receipt()también lista lo que la corrida escribió comooutputs(cadawrite_file/append_file/edit_file/zip_extract/tar_extractcon ruta y sha256), y bajoservelas dos listas son las de la request (ver Observabilidad). - Gráficos:
chart_svg(v0.6.45+:{"x_axis": {"angle", "every", "format"}}en bar/line/area/heatmap/boxplot/waterfall);chart(nodo de contenido negociado);svg_to_png(svg, opts?)/svg_to_pdf(svg, opts?)— opts de PNGwidth,height,scale,background,max_pixels; de PDFwidth,height; los dosfonts(v0.6.20+,file.readpor archivo de fuente; v0.6.45+: fallback por glifo, como mucho 16 fuentes / 64 caras) ymax_text_chars(v0.6.45+, default 16 384 caracteres por<text>);qr_matrix(data, {ecc, version})→ filas de 0/1 yqr_svg(data, {ecc, version, module, margin, dark, light})→ texto SVG (v0.6.45+, puros, ISO/IEC 18004) — ver CSV, estadística y gráficos. - I/O (gateado por capacidad):
read_file,write_file,append_file,edit_file(necesitafile.readademás defile.write, v0.6.45+),file_exists,file_info,list_dir(cada entrada traeis_link, v0.6.45+),grep(sobre una carpeta necesitafile.read("<carpeta>/**"), v0.6.45+),read_file_bytes(read_file,read_file_bytesyedit_filedicen por qué no pueden leer un archivo, v0.6.45+:File not foundes solo para lo que no existe — ver Errores); v0.6.20+:delete_file,delete_dir(file.write, sobre cada ruta borrada),cwd()(file.read(".")), archivoszip_create,zip_extract,tar_create,tar_extract(solo nativo;file.writesobre cada ruta escrita), prefijosbundle:/disk:en las lecturas — ver Archivos e I/O. - HTTP:
http,http_get,http_post,http_put,http_delete,fetch(v0.6.20+: un body map/lista sale como JSON con suContent-Type, y la respuesta traejson);http_bytes(los bytes exactos:{status, ok, bytes, headers}),multipart_encode(puro). v0.6.45+: todo builtinhttp*toma argumentos con nombre (http_get(url, headers = …, query = …, timeout = …),http(method = …, url = …, body = …)), y elfetch(url, method, …)posicional está deprecado (se va en v1). Ayudantes puros (v0.6.45+):header(r, name)(un header de la respuesta sin importar mayúsculas; una respuesta o un mapa de headers),url_encode(text)/url_decode(text)(RFC 3986, estricto,+no es un espacio),html_select(html, css)→[{tag, attrs, text, html}],html_text(html),html_unescape(text)(parsing WHATWG; el resultado conserva los labels de la entrada) — ver Cliente HTTP. v0.6.46+:form = {…}manda un bodyapplication/x-www-form-urlencoded(http,http_bytes,http_post,http_put,fetch); un secreto ligado al host (require secret("K") for net("h")) puede ir en la URL, la query, el body o el form; unnetcon comodín llega sólo a direcciones públicas; las redirecciones nunca se siguen — ver Cliente HTTP. - WebSocket:
ws_connect,ws_send,ws_recv,ws_close, más multiplexado/resilienciaws_select,ws_select_all,ws_broadcast,ws_status,ws_stats(todos gateados pornet). Opts dews_connect:subprotocols,max_queue,max_queue_bytes,on_full,reconnect({max_retries, backoff, backoff_max, on_reconnect}),keepalive({interval, timeout}). - Blockchain (puros):
keccak256,sha512_256,secp256k1_verify/recover/pubkey(secp256k1_recoveracepta v = 27/28),ed25519_verify/pubkey,evm_address(eraeth_address; también desde 20 bytes crudos),rlp_encode/decode,abi_encode/decode/selector(abi_encode(types, values)sin selector para argumentos de constructor),abi_event_topic,abi_decode_log,eip191_digest,eip712_digest, los builders EVMevm_tx/evm_tx_raw(erantx_eip1559/tx_eip1559_raw;evm_tx_rawrecalcula el digest y rechaza un map editado después deevm_tx),evm_tx_create(deploy de contratos, v0.6.29+),evm_create_address,evm_create2_address,evm_signature(v = 27/28 para wallets yecrecover),solana_tx(construye el mensaje — erasolana_message),solana_tx_raw(ensambla la transacción firmada),solana_pda,spl_ata,spl_transfer_data,spl_transfer_checked_data,algorand_tx(los bytes a firmar — eraalgorand_tx_encode),algorand_tx_raw(la transacción firmada),algorand_address(eraalgo_address),bytes_to_int,int_to_bytes,int_to_bytes_le— ver Blockchain. - Blockchain (gateados):
secp256k1_sign/ed25519_sign/schnorr_sign(require sign);mnemonic_generate,mnemonic_to_seed,hd_derive,algorand_mnemonic,keystore_import/keystore_export,wif_import(require wallet). - Bitcoin (puros):
hash160,btc_address,btc_address_decode,btc_script,btc_txid,schnorr_verify,schnorr_pubkey,btc_tx,btc_tx_raw,psbt_encode,psbt_decode,psbt_finalize. - Bitcoin (lado de lectura, gateado por
net):btc_utxos,btc_balance,btc_fee_estimates,btc_send,btc_wait,btc_rpc. - Lado de lectura de blockchain (gateado por
net, como HTTP):evm_rpc,evm_nonce,evm_balance,evm_gas_price,evm_chain_id,evm_estimate_gas(url, tx, block?),evm_call,evm_fee_history(url, blocks?, percentiles?, newest?),evm_send,evm_receipt,evm_wait, y nuevos en v0.6.29evm_block_number,evm_logs(eventos; se decodifican conabi_decode_log);solana_rpc,solana_latest_blockhash,solana_balance,solana_send,solana_wait(erasolana_confirm),spl_balance;algorand_params,algorand_account,algorand_send,algorand_wait. Los nombreseth_*de v0.6.28 son alias deprecados (tabla de arriba). - DB:
db_open,db_close,sql,sql_exec,sql_batch,sql_tables,paged;mongo_find,mongo_find_one,mongo_insert,mongo_insert_many,mongo_update,mongo_delete,mongo_count,mongo_aggregate,mongo_collections;redis_get/set/del/exists/mget/mset/keys/type,redis_incr/decr/incrby,redis_expire/ttl/persist,redis_hget/hset/hdel/hgetall/hincrby,redis_lpush/rpush/lpop/rpop/lrange/llen,redis_sadd/srem/smembers/sismember,redis_lock/unlock— ver SQL, Mongo y Redis. - Serve — respuestas, contenido, estado:
ok,created,not_found,fail,html,respond,redirect,binary,render,with_header,set_cookie,clear_cookie; nodos de contenidopage,heading,prose,list,ordered_list,link,image,section,code,raw,content,chart; estado compartidostate_set,state_get,state_incr,state_delete,state_all, y los atómicosstate_merge(key, map)→ el mapa combinado ystate_cas(key, expected, new)→ bool (v0.6.45+);openapi_json()(v0.6.20+: el documento OpenAPI publicado como texto — solo bajoserve) — ver Servidor HTTP. - Apps agénticas (engine v0.6.7+ — ver Apps agénticas): una sola espera
select(targets, timeout?); TCP crudotcp_connect(host, port, opts?)(con el permisonet("host:puerto")),tcp_send,tcp_recv,tcp_close,tcp_statsy pipes de bytes en memoriapipe(opts?),pipe_send,pipe_recv,pipe_close(v0.6.42+, los dos enselect); v0.6.45+:tcp_write(conn, data)/pipe_write(end, data)toman lo que entra ahora y devuelven cuántos bytes tomaron, sin esperar nunca (0= lleno ahora;tcp_send/pipe_sendsiguen siendo todo-o-timeout),pipe_stats(end)→{queued_in, queued_out, status}, y un reset del otro lado llega como{type: "close"}en vez de un error; procesos vivosproc_spawn,proc_recv,proc_select,proc_send,proc_close_stdin,proc_resize(v0.6.8+, sólo pty),proc_status,proc_kill,proc_wait,proc_stats,proc_close(gateados porexec, comorun;proc_spawn(…, {"pty": true})desde v0.6.8; el kill alcanza al árbol de procesos entero y{"process_group": false}desprende a propósito, v0.6.9+); file-watchwatch,watch_recv,watch_stats,watch_close(v0.6.9+, gateados porfile.readcomolist_dir; polling con snapshot, los mismos eventos en todos los SO); la terminal propia del programaterm_open,term_recv,term_size,term_write,term_stats,term_close(v0.6.11+, gateados porstdin; raw mode, cada tecla como evento, entra enselect;term_openesnothingsin TTY); bus de eventosbus_publish,bus_subscribe,bus_recv,bus_unsubscribe,bus_topics(sin capability); control de agentesagents,agent_stop; el bindingsocketde un bloqueroute … socketes un handle WebSocket para la familiaws_*. - Programa y subproceso (engine v0.6.14+):
steps()→ sentencias ejecutadas hasta ahora (v0.6.20+; determinista, sin capacidad — ver Observabilidad);args()→ el argv propio del programa (lo que sigue a--ensynsema run, o el argv entero de un binariosynsema build) — sin capability (es input que tipeó quien llama);self_path()→ el path de este ejecutable, exactamente como lo da el SO (pasáselo arun/proc_spawn— el scopeexeccoincide byte a byte) — sin capability;platform()→{os, arch}(v0.6.18+:"windows"/"macos"/"linux"y otros nombres tal como los reporta Rust;"x86_64"/"aarch64";"wasm"/"wasm32"en el build para navegador) — sin capability, la misma respuesta bajo--sandboxy--profile pure(un hecho del binario, comoargs());shutdown(reason?)(v0.6.18+) → le pide al server que corre su drain ordenado y exit 0 — desde una ruta, un socket, un job de cron o un agente; idempotente; error bajoruny antes de que algo escuche; un motivosecretse rechaza; sin capability — ver Tu app en el escritorio;run_program(source, opts)—require sandbox_run— corre otro programa Synsema en un proceso hijo bajo un techo que es la intersección con el del padre, con su propioenv/cwd/timeouty su audit devuelto como un valor — ver Correr Synsema bajo un techo. - LLM / tools:
llm_available,llm_usage(tokens consumidos por este proceso;0offline — ver Primitivas LLM),llm_step,call,call_tool. v0.6.46+:tool_spec(task, describe)arma la entrada del catálogo dellm_stepdesde la firma de una task ({name, describe, params: ["a: number", …], optional}), ycall/call_toolchequean los parámetros tipados (task f(a: number, b: text = "x")) de forma estricta, sin convertir — ver Tool calling. - Judge (System One, v0.6.25+): el bloque
judgees sintaxis, no un builtin (ver Judge); su introspección esjudge_available()(hay provider cableado),judge_usage()(tokens de entrada consumidos por este proceso; la salida es gratis),judge_model()(el id versionado del modelo que contestó el último bloque, onothing). Sin gate. - Dinero / ledger de gasto (
require spend("UNIDAD")— ver Capacidades):spend(monto, unidad, motivo)→ total acumulado de la unidad (auditado enspend.log, techo del hostSYNSEMA_SPEND_CEILING);spend_total(unidad)→ total del proceso, sin capability. - Memoria / progreso / reglas (toda la familia necesita
require memory("name")— ver Memoria y estado):remember,recall,forget_memory,memory_summary,create_progress,start_step,complete_step,fail_step,resume_point,progress_display,progress_percent,add_rule,check_rules,get_rules. - Cómputo confidencial (engine v0.6.24+ — ver Etiquetas y Attestation): etiquetas
private,declassify,label_of,is_private(bajo--labels, siempre encendidas conserve --attestedy dentro de un guest); attestationattest,attest_key(require attest),attestation_document,attestation_key(la identidad de unserve --attested; la clave está sellada —revealla rechaza),attestation_verify(puro,opts.nowobligatorio);groth16_verify(Groth16 sobre BN254, el JSON de snarkjs tal cual); ruido determinista para privacidad diferenciallaplace_noise,gaussian_noise(misma semilla → mismo ruido, así repetir una consulta no promedia el ruido hacia el valor real). Variantes totales para input no confiable, que es cómo validás sin fallar cuando un error sería en sí mismo un bit:json_decode(x, default),number(x, default),aes_gcm_decrypt(k, n, ct, aad, default),decimal,float,toml_parse,abi_decode,bech32_decode,rlp_decode. v0.6.46+:declassifyyprivatesólo se llaman por su nombre; con etiquetas,declassifyes una capacidad que acota el techo del host (--cap-set declassify=<principal>); un dato privado llega a un modelo sólo conrequire llm("P")+ elllm=P@<proveedor>del host; el prompt deread_linees un sumidero público; un recibo sellado para un auditor (--auditor) deja correrreveal/signen una rama privada — ver Etiquetas y Observabilidad. - Secretos:
secret,as_secret,bearer,reveal. v0.6.46+: un secreto ligado a los hosts a los que puede ir,require secret("K") for net("api.example.com"), va en una URL, una query, un body JSON o un form (uno sin ligar, sólo en un header); lo que el servidor devuelve como eco se enmascara como[secret K]— ver Secretos. - Respuestas (serve):
ok,created,fail,not_found,respond,redirect,render,content,paged;form of request(body de formulario parseado urlencoded/multipart, archivos como bytes exactos). - Errores:
raise,assert,assert_eq,assert_ne,assert_error.