This document defines the supported production execution surface for Geno.
Safe Defaults
geno.run()andgeno.check()are the supported entry points.- Hosted deployments should instrument
geno.run()throughRunConfig(monitoring_hook=...)or the helper collector ingeno.monitoring. - If
RunConfig.capabilitiesis omitted, capability gating fails closed. - Every gated builtin is denied unless its capability is present.
- Interpreter filesystem builtins and HTTP client builtins require both the matching capability and an explicit host callback.
- Module imports resolve from
RunConfig(modules=...), not from the filesystem.
Pure Builtins
The following builtin families are part of the supported runtime surface and remain available even when capabilities=set():
- List:
length,head,tail,append,concat,set_at,slice,filter,map,fold,contains,take_while,all,reverse,range,sort,sort_by,zip,enumerate,flat_map - Set:
set_new,set_from_list,set_add,set_remove,set_contains,set_size,set_to_list,set_union,set_intersection - String:
split,join,trim,to_lower,split_once,starts_with,to_chars,sort_strings,substring,contains_substring,repeat_string,to_upper,replace,ends_with,format - Math and conversions:
add,subtract,multiply,divide,sqrt,floor,ceil,round,max,clamp,abs,square,parse_int,parse_float,to_string,float_to_int,int_to_float - Predicates and helpers:
is_sorted,is_positive,is_numeric_string,is_permutation - Option:
is_some,is_none,unwrap,unwrap_or - Map:
map_insert,map_get,map_from_list,map_entries,map_from_entries,map_merge,map_filter_map,map_map_values - Array:
array_new,array_from_list,array_get,array_set,array_length,array_to_list,array_fill,array_copy - Vec:
vec_new,vec_from_list,vec_push,vec_pop,vec_get,vec_set,vec_length,vec_to_list - MutableMap:
mutable_map_new,mutable_map_set,mutable_map_get,mutable_map_contains,mutable_map_delete,mutable_map_size,mutable_map_keys - Char codes:
char_code,from_char_code - JSON/CSV/TOML:
json_parse,json_stringify,json_to_string,csv_parse,csv_parse_with_headers,toml_parse
Capability-Gated Builtins
printrequiresprintclock_now,clock_format,clock_parse,clock_elapsedrequireclockrandom_int,random_floatrequirerandomfs_read_text,fs_write_text,fs_list_dir,fs_exists,fs_metadata,fs_symlink_metadata, andfs_canonicalizerequirefs(all require host callbacks in the interpreter)http_fetch,http_post,http_requestrequirehttp(fetch/post/request also need host callbacks)regex_match,regex_find_all,regex_replacerequireregexenv_get,env_get_or,cli_argsrequireenvexec,exec_with_inputrequireprocesshttp_listen,http_route,http_respondrequireserve
Sandbox Constraints
Sandboxed Geno execution blocks ambient access to:
- filesystem I/O
- network I/O
- process and OS execution
- dangerous Python builtins such as
eval,exec, andcompile - reflection attributes commonly used in sandbox escapes
Additional constraints:
RunConfig(timeout=...)is enforced through the interpreter deadline path cooperatively; a builtin or host callback that holds control cannot be preempted by the in-process interpreter- step budgets default to
RunConfig(max_steps=1_000_000)and apply only to the interpreter / thread-sandbox path; theProcessSandboxpath bounds compiled Python via wall-clock, memory, collection-size, integer-bit, and recursion limits instead. Explicitmax_steps=Nonedisables the cooperative interpreter step budget RunConfig(max_output_length=...),RunConfig(max_collection_size=...),RunConfig(max_integer_bits=...), andRunConfig(max_recursion_depth=...)apply to interpreter execution- OS-backed process limits (
max_memory_bytes,max_cpu_time,max_file_size_bytes, andmax_processes) are not available throughRunConfigbecausegeno.run()is an in-process embedding API - the default process-memory budget is 512 MiB on Darwin and 256 MiB elsewhere; callers can explicitly select a different finite value
- on Darwin,
max_memory_bytesis an address-space growth budget above the trusted Python worker's pre-input raw VM-map size. Geno probes XNU's actual soft-limit acceptance boundary before reading input, avoiding architecture and kernel-version assumptions while preserving inherited hard limits. Later request parsing and trusted setup consume that budget before untrusted code runs, and any stricter inherited hard limit still wins SandboxConfigcan express everyProcessSandboxConfigresource limit for callers that userun_sandboxed()/ compiled process execution: timeout, memory bytes, CPU time, file size, process count, output length, collection size, integer bits, recursion depth, and print allowancemax_integer_bitsandmax_collection_sizeare forwarded to theProcessSandboxworker so compiled code's_safe_add/_safe_muland pre-allocation checks honor the configured values- output is capped by sandbox configuration
Supported Module Model
- imports are satisfied from the in-memory
modulesdictionary - transitive modules must also be present in that dictionary
- circular imports are rejected
- Geno does not read module source from disk during execution
Benchmark Python Import Allowlist
The benchmark runner has a restricted Python namespace for comparison work. Its supported import allowlist is intentionally small:
typing
All other imports are rejected.
Raw Python benchmark execution is also opt-in at the API level:
BenchmarkRunner()does not allowevaluate_python()- use
BenchmarkRunner.for_research()or passallow_unsafe_python_execution=Trueonly in controlled local research workflows
Compilation Targets
| Target | Command | Output | Runtime |
|---|---|---|---|
| Python | geno compile <file> | Python source | Python 3.10-3.13 |
| JavaScript | geno compile --target js <file> | JavaScript source | Node.js |
The JS backend emits standalone JavaScript that includes the runtime prelude. It does not require any npm packages. The JS compilation path uses the same lexer, parser, and typechecker as the Python path; only the code generation differs.
Note: The JS backend does not include a sandbox. It is intended for trusted execution environments (e.g., local development, server-side Node.js with appropriate process isolation).
Execution Entry Points -- Security Model
| Entry point | Trust level | Intended use |
|---|---|---|
geno.api.run() | Production embedding API -- in-process interpreter with cooperative timeout and capability gating | Host-controlled embedding where the caller owns process isolation |
geno run --json | In-process CLI -- embedding API with cooperative timeout; capabilities must be granted explicitly | JSON results for trusted code or a caller-managed worker |
geno.server (POST /run) | Production hosted boundary -- delegates to geno.api.run() in a child process with hard wall-clock timeout | HTTP API for untrusted hosted execution |
geno.server (POST /constrain) | Production -- validates prefixes in a child process with hard wall-clock timeout and returns allowed-next-token guidance | HTTP API for hosted constrained decoding |
compile_and_exec() | Build-time / trusted -- optional timeout, no process isolation | Tests, tooling, trusted callers only |
compile_to_js() | Build-time / trusted -- no sandbox, no process isolation | JS code generation for trusted environments |
REPL (geno repl) | Local / trusted -- 30 s UX timeout, no process isolation | Developer interactive use |
| Benchmark runner | Research-only -- restricted namespace, not a security boundary | Local evaluation of LLM-generated Python |
For untrusted code, use the hosted server boundary or wrap geno.api.run() in
caller-managed process isolation. Do not rely on the in-process embedding API
alone for killable wall-clock isolation.
Cross-backend numbers, copies, map ordering, lookup, and output are specified in Portable Runtime Semantics.
Hosted /run and /constrain workers use multiprocessing.get_context("spawn")
and fail closed with WorkerSpawnFailed if a killable child process cannot be
created. There is no supported thread-timeout fallback for hosted untrusted
execution.
Hosted workers enforce GENO_MAX_RESPONSE_BODY_BYTES before sending results
back to the server process. Oversized /run and /constrain results return
HTTP 413 with a fixed error body, while completion metrics are retained. The
HTTP handler also checks response size before sending headers. Request source,
module source, and constraint prefixes must be valid Unicode text; unpaired
JSON surrogate escapes and out-of-range timeouts return HTTP 400.
Production Boundary
The production security boundary is the Geno runtime and sandbox. The benchmark runner's raw Python executor is not a supported production sandbox for untrusted Python and should only be used for local research and evaluation workflows.
For hosted services, the deploy-facing health and metrics contract is also part of the supported surface:
RunConfig(monitoring_hook=...)receives aRunMetricspayload on everygeno.run()completionRuntimeMetricsCollector.snapshot()returns a stable JSON-serializable metrics snapshot for hostedgeno.run()results and/constrainevaluationsRuntimeMetricsCollector.health_report()returns a stable JSON-serializable health payloadMetricsSnapshot.to_prometheus_text()exposes the same counters in text form for Prometheus-style scraping
Rendered from docs/runtime/execution-surface.md in the Geno repository.