Blocks
A block is the smallest unit of a delegated result. Each one is a pair:
type— what kind of result this is (detection,marker, …). The ingest core routes on it.data— the body in that type’s own shape, the same typed payload the platform already validates.
A stage returns its result as a block envelope — an ordered list of blocks — and the ingest core decodes and stores each one independently. The envelope shape and how it is routed are covered in Ingest; this section is the catalogue of block types and the data contract behind each.
The block types
The core ships a small, closed set. A producer stamps each block’s type with one of these:
type | What it is | data shape | Stored as | Writable from |
|---|---|---|---|---|
detection | A run of detection tracks/boxes (people, vehicles, faces, …). | PostDetectionsRequest | a DetectionRun in the detections collection, keyed by (key, source.runId) | API and pipeline |
marker | A single timeline annotation — a labelled point or span on the recording. | Marker | a Marker in the markers collection, keyed by (organisation, device, name, startTimestamp) | pipeline only |
A block’s type names the result shape, not the stage that produced it. A stage that finds bounding boxes emits a detection block whatever it is detecting, and one envelope may carry several blocks of different types.
Type, not variant
The type names the shape, not the flavour. Variants that share a shape are the same type:
- Inside
detection,boxandposeboth report an axis-aligned box per frame, share one contract (PostDetectionsRequest) and onedetectionscollection — so they are the same block type. - A result whose shape is genuinely different — a marker is a timeline annotation, not a box per frame — is its own block type.
So most new capabilities don’t add a block type; they recombine the existing ones. A new type is only needed when the shape of the data is new, and it arrives as a new handler in the core.
The contract is the stable part
A block type’s data contract is defined once in @uug-ai/models and is the same wherever the block comes from. A detection block has the same body whether your microservice emits it as a workflow stage over the queue or your own service posts it to the ingest API. The transport decides who triggers the work and which deployments can use it; it never changes the data. So each page below documents the contract first — the transport is a delivery choice layered on top.
The contracts
- Detection — a run of detection tracks (a box per frame, per tracked object) for a recording, delivered as a
detectionblock and stored in thedetectionscollection. Emittable from a workflow stage or the ingest API. - Marker — a labelled point or span on a recording’s timeline (a licence-plate read, a point-of-sale transaction, an alert window), delivered as a
markerblock and stored in themarkerscollection. Emittable from a workflow stage only.