Handler runtime
The handler preset has two runtime profiles. Python 3.12 is generally available. Node.js 22 is
released through a capability- and policy-gated rollout; it can be prepared in source while its
creation or dispatch switch remains disabled for a particular environment.
Handler contracts
Section titled “Handler contracts”| Runtime | Entry file | Export | Result |
|---|---|---|---|
| Python 3.12 | /app/handler.py |
callable handle(input) |
any value accepted by json.dumps |
| Node.js 22 | /app/handler.ts |
named handle(input) |
a JSON value or a promise of one |
For both runtimes:
- input is a JSON object and defaults to
{} - returning normally succeeds the run
- an uncaught exception or a non-serializable result fails it
- the handler module is initialized once per runtime process
- invocation-specific data must not be stored in mutable module globals
Python helpers
Section titled “Python helpers”Magmell supplies siloga_agent; do not add it to requirements.txt.
import siloga_agent
def handle(input: dict): token = siloga_agent.secret("TOKEN") siloga_agent.log("starting", item_id=input.get("id")) with siloga_agent.span("work"): result = work(input, token) siloga_agent.metric("result.items", len(result)) siloga_agent.event("work.complete") return resultsiloga_agent.secret(name) returns the current invocation’s string value or None. Python
ContextVar keeps secret and event state scoped to the invocation.
TypeScript helpers
Section titled “TypeScript helpers”@siloga/magmell-agent is the in-handler Agent SDK, distinct from the @siloga/magmell
control-plane client. Declare its exact compatible version as a devDependency; the platform
supplies the protected runtime copy.
import { event, log, metric, secret, span } from '@siloga/magmell-agent'
export async function handle(input: { id?: string }) { const token = secret('TOKEN') log('starting', { itemId: input.id }) return span('work', async () => { const result = await work(input, token) metric('result.items', result.length) event('work.complete') return result })}secret(name) returns string | undefined. Node’s AsyncLocalStorage scopes secrets and events
across awaited work, including when multiple invocations overlap. Calls made after an invocation
has finished do not emit into a later invocation.
See the Agent SDK reference for exact helper signatures.
Event behavior
Section titled “Event behavior”Both runtimes expose the same concepts:
| Helper | Purpose |
|---|---|
log |
structured diagnostic message with debug, default, warning, or error level |
event |
named point-in-time domain event |
metric |
named measurement with structured dimensions |
span |
timed operation, emitted even when the operation raises or rejects |
Values are normalized to bounded JSON at emission time. Unsupported or oversized event data is replaced with a diagnostic marker so it cannot corrupt the full invocation response. Events emitted before an exception are retained.
Concurrency and mutable state
Section titled “Concurrency and mutable state”Runtime processes can handle overlapping invocations. The platform helper context is isolated, but
your own module globals are not. Module scope is suitable for immutable configuration and reusable
clients; keep request-specific values inside handle and its asynchronous call chain.
Files and build policy
Section titled “Files and build policy”Nested source files are supported, while runtime-owned paths, credentials, absolute paths, and path
traversal are rejected. handler.py, handler.ts, package.json, and package-lock.json must be
top-level when applicable. A deployment may instead select the command preset to run an exact
entrypoint argv; see command deployments. Ordered setup steps run
during the build; see Setup and dependencies.
Before offering Node deployments, a gateway reports node-22 from /v1/capabilities with separate
creation_enabled and dispatch_enabled states. The former gates deployment creation; the latter
gates runs. Clients must check the state for the operation they are about to perform rather than
assuming that recognition of the runtime ID means every phase is live.