Command deployments
A deployment normally runs a handle function (the handler preset). The command preset instead
runs an exact process you choose: the platform starts your entrypoint argv, delivers the run input
on stdin, and returns what the process writes to stdout. This lets you deploy an existing CLI or an
agent-framework program without wrapping it in a Magmell handler.
Deploy a command
Section titled “Deploy a command”Pass --preset command and give the exact argument vector with a repeatable --entrypoint. The
first --entrypoint is the executable; the rest are its arguments, in order.
# Python 3.12magmell deploy ./agent \ --name my-agent --version 1 \ --preset command --entrypoint python --entrypoint main.py \ --wait
# Node.js 22magmell deploy ./agent \ --name my-agent --version 1 \ --runtime node-22 \ --preset command --entrypoint node --entrypoint dist/agent.js \ --waitThe entrypoint is an argv array, not a shell string: there is no shell expansion, word splitting, or
interpolation. It carries 1 to 64 items; each item is at most 4 KiB and the whole vector is at most
16 KiB. --entrypoint values may look like flags (--entrypoint --verbose is a literal argument).
The command preset is available for python-3.12 and node-22. A command deployment needs no
handler.py or handler.ts; requirements.txt, explicit --requirements, package-lock.json, and
setup steps work exactly as they do for handlers. Node command
deployments run your precompiled JavaScript — Magmell does not compile TypeScript for a command,
so commit the build output (for example dist/agent.js) and point the entrypoint at it.
The input/output contract
Section titled “The input/output contract”- Input arrives as a single line on stdin: the run’s
inputas normalized UTF-8 JSON bytes followed by one\n, after which stdin is closed. A program that ignores stdin (anecho-shaped command) is fine — the platform tolerates a broken pipe and does not fail the run for it. - Output is whatever the process writes to stdout, up to 1 MiB. On a successful exit it becomes
the run’s result as a JSON string, returned verbatim — not parsed, not trimmed. Empty stdout
produces the empty string
"", which is a real result, distinct fromnull(“no result yet”). - Working directory is
/app. Secrets are provided as environment variables (see below). - Logs: everything the process writes to stderr goes to the run logs, with secret values redacted.
The process starts in a new process group under a single deadline that covers stdin delivery, execution, and stdout collection.
Success and failure
Section titled “Success and failure”A run succeeds only when the process exits 0 and its stdout is valid UTF-8 with no NUL byte.
Otherwise it fails with an explicit category. When more than one condition holds at once, the
category is chosen by this precedence, highest first:
- deadline — the timeout expired;
- output too large — stdout exceeded 1 MiB;
- terminated by signal — the process died on a signal (for example an out-of-memory kill), reported with the signal number;
- non-zero exit — reported with the exit code;
- invalid stdout — not UTF-8, or contains a NUL byte.
On any failure the captured stdout is discarded and never appears in the result or the error. The bounded error names the category (and the exit code for a normal non-zero exit); it never contains your stdout or stderr.
Secrets and environment
Section titled “Secrets and environment”Deployment secrets are passed to the process as environment variables under their
exact names, so conventional provider settings such as OPENAI_API_KEY and OPENAI_BASE_URL work
without a wrapper. The child environment is a fresh copy of a curated safe base plus the runtime’s
default PATH, then your secrets applied last (last-write-wins — a secret named PATH deliberately
replaces the default, after which bare names like node may no longer resolve). On Python the
pip console-scripts directory is on the default PATH, so an entrypoint like
["uvicorn", "app:app"] resolves; on Node node_modules/.bin is on the default PATH.
An argv[0] with no / is resolved through PATH; an argv[0] containing / is resolved relative
to /app and is not PATH-searched.
Timeout and retries
Section titled “Timeout and retries”The effective timeout is an integer from 1 to 3600 seconds and is the run’s single deadline. An
explicit out-of-range or non-integer timeout_s is rejected. On expiry the platform terminates the
whole process group, waits a short grace, then force-kills it.
Command deployments require max_retries = 0. An omitted value resolves to 0 for a command even
when the server’s handler default is non-zero; an explicit non-zero value is rejected at admission
and at run time. This is intentional and asymmetric with the timeout: a one-shot customer command may
not be idempotent, so a silent retry could run side effects twice — retries are forced off, while a
timeout is benign and merely enforced.
Numeric fidelity
Section titled “Numeric fidelity”The platform delivers the input bytes to stdin at full precision: JSON integers larger than JavaScript’s safe range (2⁵³) are preserved as sent. Parsing is entirely your program’s concern, and the common parsers lose precision by default:
- Node: plain
JSON.parsetruncates large integers to doubles. Use a bigint-aware parser (for examplejson-bigint) when you need full fidelity. - Python:
json.loadskeeps arbitrary-precision integers, but decimal values become floats; passparse_float=Decimalwhen exact decimals matter.
Because the result is an unparsed string, there is no corresponding concern on the output path.
Not supported
Section titled “Not supported”The command preset is a one-shot run — one process, one final result. It does not provide streaming run responses, persistent sessions, resume tokens, cross-run memory, human-in-the-loop pause/resume, scheduled or background execution, or automatic retries after the process starts. Workloads that need those require a protocol beyond one-shot runs.
Compatibility
Section titled “Compatibility”Magmell classifies command-preset workloads with four labels, each with its own evidence bar:
- Certified — covered by the regression suite; a regression blocks release.
- Certified example — a shipped example, smoked in CI against a loopback stub and run through the executors.
- Generic — works through the generic command contract, but is not validated per framework and may break without notice.
- Unsupported — needs a protocol or state model beyond one-shot runs.
| Workload | Label |
|---|---|
| Existing Magmell Python/Node handler | Certified |
| Plain Python/Node one-shot CLI | Certified |
| Other one-shot executable (shell script, static binary) | Generic |
| OpenAI Agents SDK (Python/TypeScript), one logical run | Certified example |
| Client-executed stdio MCP tool inside that run | Certified example |
| Client-executed Streamable HTTP MCP | Generic |
| Other one-shot frameworks or CLIs | Generic |
| Claude Agent SDK | Generic |
| Streaming, persistent sessions, human-in-the-loop resume | Unsupported |
The Claude Agent SDK runs as an ordinary customer command; Magmell makes no provider-independence claim for it. Mistral-specific integration is out of scope.