Skip to content

Running the model

The handler

@adapter.on_image()
def detect(call):
    return [call.detection("fallen", 0.91, 0.1, 0.2, 0.3, 0.4)]

call is everything about one request:

call.image / .audio / .data the binary payload
call.text the prompt, for a text adapter (checks text, prompt, input)
call.params everything the caller sent besides the body
call.param(name, default) one of them, with a default
call.task which advertised task this call is for
call.camera_id the camera, when the caller knows it
call.model whatever @adapter.load() returned
call.payload the raw dict AdapterService.infer would have received

One adapter has one handler and one body shape. To serve several tasks, branch on call.task inside it — that keeps /capabilities honest about a single input shape.

Returning an answer

return [call.detection(...), ...]     # §5.1 detections
return {"caption": "a van at the gate"}   # your own shape, verbatim
return InferResponse(...)             # full control of the envelope

call.detection builds a contract-shaped item and clamps the coordinates to 0–1, because normalized-versus-pixel is the mistake that survives every test you write and only shows up as a box in the wrong place on someone's screen.

Follow a convention where one exists

    """The precise route, when you want the frame dimensions too — the
    contract types validate the shape before it reaches the wire, so a
    box outside the frame fails here rather than in someone's UI."""
    return DetectionResult(
        detections=[DetectionItem(
            label="person", confidence=0.94,
            bbox=NormalizedBBox(x=0.11, y=0.22, w=0.13, h=0.41),
            track_id=7, attributes={"pose": "standing"},
        )],
        frame_dimensions=FrameDimensions(w=1920, h=1080),
    ).model_dump(mode="json")

The convention types validate before the data reaches the wire, so a malformed result fails in your process rather than in a consumer's.

Full example: 03_result_conventions.py.