monty runs python3 in-process, sandboxed, stdlib-only:
perfect for quick one-liners and pipe transforms, useless for a script that
imports pandas. A docker entry is the opposite: your container, your
installed packages, but every line pays the exec round-trip. The route
decides per line which one serves it:
route.py
python3 /jobs/train.py --epochs 3 runs in the container, while
cat data.csv | python3 -c "import sys; print(len(sys.stdin.read()))"
stays on monty.
Input: the line’s context
The script sees one global,ctx, the parsed line before any routing.
This payload is captured from a live run of the config above, routing
python3 /jobs/train.py --epochs 3:
commands: one entry per pipeline stage (cat x | python3 -has two), each with its full words and its absolute-path operands.command,builtin: mirror the first stage.builtinmeans mirage has a builtin spec for the command (python3is a builtin that hands its code to a runtime), as opposed to an unknown name.env: the session environment (empty here, noexportyet).session_id: the executing session’s id.agent_idis empty until an agent identity is attached.mounts: the workspace’s mount prefixes, including built-ins like/dev/.
RouteContext.from_dict), so you
can store one and replay a decision in tests.
Output: the verdict
- A runtime name (
"docker"): that entry serves every command it captures on this line. None: no opinion; the first capturer in theruntimeslist order serves each command (here,monty).- Anything else is a routing error; the line fails rather than guessing.
route, each runtime entry can carry its own script:
with the same ctx input but a boolean verdict: am I willing to serve this
line? Unwilling entries step aside and the first willing capturer wins.
What runs the scripts
route.py is never imported: the workspace evaluates its source on the
policy engine, the first entry in the runtimes list with the
evaluator capability. In the config above that is monty. A config with
route scripts but no evaluator entry fails at the first decision.
When you build the workspace in code rather than from a config file,
route= also accepts a plain function with the same decision contract,
sync or async. It is called directly, so no evaluator is involved:
script= likewise accepts (ctx) -> bool in code.
Bring your own
The capability is open: inheritEvaluatorMixin (Python) or implement
Evaluator with the EVALUATOR brand (TypeScript) on your own runtime,
and it becomes eligible as the policy engine. eval(code, inputs=...)
returns the last expression’s value; how the value travels is your
runtime’s choice. The docker examples give a stock container the
capability by piping a harness to python3 -:
python,
typescript.