Write a handler
Every handler deployment uses the handler preset and must contain a top-level handler.py file
with a callable named handle.
def handle(input: dict): return {"received": input}Input and output
Section titled “Input and output”The handler receives the run’s input object. If a run omits input, the runtime passes an empty
dictionary. Return a value accepted by Python’s json.dumps, such as a dictionary, list, string,
number, boolean, or None.
def handle(input: dict) -> dict: numbers = input.get("numbers", []) return {"sum": sum(numbers), "count": len(numbers)}An uncaught exception fails the run. Magmell captures its type and message for the run record while protecting secrets from gateway logs.
Package requirements
Section titled “Package requirements”Add a conventional requirements file beside the handler:
httpx==0.28.1pydantic==2.11.7Then deploy the directory normally:
magmell deploy ./summarizer \ --name summarizer \ --version 1 \ --waitPin exact versions for repeatable production builds. Standard-library-only handlers do not need
requirements.txt. For system packages and other build commands, see
setup and dependencies.
Initialize reusable resources once
Section titled “Initialize reusable resources once”The runtime imports handler.py once when it starts. Put reusable client initialization at module
scope and invocation-specific work inside handle.
import httpx
client = httpx.Client(timeout=20)
def handle(input: dict) -> dict: response = client.get(input["url"]) return {"status": response.status_code}Do not keep invocation-specific secrets or mutable request state in module globals.
Emit structured telemetry
Section titled “Emit structured telemetry”import siloga_agent
def handle(input: dict) -> dict: siloga_agent.log("starting analysis", document_id=input.get("id")) with siloga_agent.span("analyze"): result = analyze(input["text"]) siloga_agent.metric("input.characters", len(input["text"])) siloga_agent.event("analysis.complete", confidence=result["confidence"]) return resultEvents emitted before an exception are retained, which makes them useful for diagnosing failed runs. See events and logs.
Read secrets explicitly
Section titled “Read secrets explicitly”import siloga_agent
def handle(input: dict) -> dict: api_key = siloga_agent.secret("MODEL_API_KEY") if not api_key: raise RuntimeError("MODEL_API_KEY is not configured") return call_model(api_key, input)Secrets are scoped to the current invocation. They are not environment variables and should never be returned or included in emitted event data.