NỎ THẦN AGENTIC
Technical notes

News & technical notes

These are short notes explaining why we made a specific engineering choice, written by the team that made it, grounded in the SOAI system we have built and tested through a POC acceptance cycle.

Why we chose a plugin architecture for device integration

IP cameras do not speak one language. ONVIF, VAPIX, and ISAPI are each different, so we separated image acquisition from analysis. Adding a new brand no longer touches the core.

When we started integrating cameras for the SOAI monitoring system, we ran into an inconvenient fact immediately: every camera vendor has its own protocol. Open-standard IP cameras use ONVIF Profile S and RTSP. Axis uses VAPIX alongside ONVIF. Hikvision uses ISAPI and its own SDK. There is no single API that talks to every camera in existence, and there never will be.

If device-reading logic for each brand were mixed into the AI analysis logic, every new vendor added would mean touching the core, risking breakage of something already running reliably just to add something new. So we built two separate abstraction layers: `DeviceProvider`, whose only job is to fetch images or video from a device regardless of the protocol underneath, and `AnalysisEngine`, whose only job is to analyze a frame or a video without caring where it came from.

The practical result: adding support for a new camera line means writing a new `DeviceProvider` plugin that follows the defined interface, leaving the analysis engine and the already-accepted modules untouched (SKU counting, packing video analysis, live view, and so on). Likewise, adding a new AI check means writing a new `AnalysisEngine`, and the device layer stays untouched.

This is also why we can pursue technical partnership conversations with Axis and Hikvision without rewriting the system. Even though each vendor has a different SDK and documentation, we only need one plugin conforming to the same interface contract.

Read more

Counting SKUs in blurry images: why we use SAHI with YOLOv8

A single inference pass over a whole image tends to miss small, densely packed objects. Slicing the image before running the model solves exactly that problem.

SKU counting sounds simple: count the boxes or units in a frame. But it is hard because the objects are usually small relative to the whole image, packed tightly together, and sometimes the image itself is partially blurred due to camera angle or real lighting conditions on a factory floor or in a warehouse.

A standard object detection model like YOLOv8, run once over the full image, tends to miss small objects packed densely, because the model has to take in the whole large image at once and small objects occupy too few pixels for it to detect confidently.

SAHI (Slicing Aided Hyper Inference) addresses this directly: it slices the source image into overlapping tiles, runs YOLOv8 inference separately on each tile, then merges the results and removes duplicate detections in the overlapping regions. Because each tile is smaller, a small object within it occupies a larger share of pixels, so the model detects it more accurately.

In the accepted module, combining YOLOv8 with SAHI this way delivers counts within a sub-3-second SLA, along with an exported image showing bounding boxes for each counted object. The system also records which model version produced each count, so when a customer asks why a count differs from a previous run, we can trace back to exactly which version ran.

Read more

126 test scenarios, no swallowed exceptions: how we test a monitoring system

In a monitoring system, software that looks fine while processing corrupted input is more dangerous than software that fails loudly. That is why roughly a fifth of our test suite deliberately feeds it bad data.

The SOAI test suite is organized into three layers. The first is 10 backend unit and integration suites, covering the models, the `AnalysisEngine` implementations, the asynchronous workers (Celery), and the APIs. The second is 99 end-to-end scenarios exercising the actual data flow: Upload → Process → Storage → Query, checking the whole chain from a user uploading a video to querying the result, not only that a single function works.

The third layer is 27 stress and adversarial-media tests: feeding the system blurry video or images, structurally corrupted files, QR codes that are not cleanly readable, and network connections that drop mid-processing.

Why this third layer matters more here than in typical software: if a document management app hits a corrupted file and throws an error, the user just retries. But if a monitoring system hits a corrupted video or a blurry image and silently returns "no violation found", a result that looks exactly normal, that is a genuine safety gap, because nobody knows the system has failed.

Read more

Why we have no silent fallback path

A silently swallowed exception can turn a corrupted video into a "no violation found" result that looks entirely normal. We surface it as an explicit exception, with a detailed log entry.

Picture a concrete case: a video recording of a packing run is partially corrupted by a disk write error, and when the system tries to extract frames via FFmpeg, the call fails. There are two ways a system can handle this. The first: catch the error, return an empty default result, say "no QR code found" or "no violation detected", and keep running. The second: let the failure surface as an explicit exception, with information about why it failed.

We deliberately chose the second. The entire SOAI system runs on a custom exception hierarchy called `SOAIException`, categorized by specific failure type (database errors, corrupted files, media-processing errors, device connection errors, and so on). Every fault passes through this hierarchy, surfaces as a transparent error with an RFC-compliant HTTP response, and is logged in detail.

Why this matters specifically for a monitoring system: the value of such a system rests on being able to answer a business question accurately, such as whether stock is sufficient or whether there was a safety violation. A silent fallback that returns a default on error turns a technical fault into a wrong business answer, and whoever reads the report has no way to tell "genuinely no violation" apart from "the system failed and nobody knew".

Put simply, a loud, logged error is an incident that can be fixed. A silently swallowed one is an incident that comes back to find us later, as a customer who has lost trust in what the system reports.

Read more
Support via e-post och telefon, 9:00-17:00 måndag till fredag