Commands

Central cannot open a connection to a device behind a factory NAT, so the device fetches commands by long polling, waiting up to commands_poll_s (default 25 seconds). The device always reports (acks) the result, so on screen a command moves through Queued (대기 중) → Delivered (전달됨) → Done (완료) / Failed (실패). Sending commands needs the OperateOPERATOR · ADMIN permission.

The field connects first and the centre answers on that connection. The path from the centre into the factory stops at the firewall, and there is no need to open it

  1. Open the Commands (명령) tab on the device detail page. ① Pick a command type and ② press Send command (명령 보내기).
    Commands tab — ① command type ② Send command ③ a failed command keeps the error the device reported
  2. The device picks it up on its next poll and handles it, and the outcome stays in the Result (결과) column. ③ A failed command shows the error exactly as the device reported it (here, a 404 from trying to pull a model version with no artifacts).
CommandScreen nameWhat the device doesExample result
pingPing (핑)Answers without changing anything{"pong": true, "device_id": "edge-bench-01"}
restartRestart (재시작)Ends the agent with exit code 3 — the supervisor starts it again{"restarting": true}
resyncResync (재동기화)Puts queue items folded into failed back into the queue and sends right away{"requeued": 0}
pull_modelPull model (모델 내려받기); a deployment from the Models tab sends itPulls and activates the model given by {name, version, activate, deployment_id}. A failed activation is reported as failed{"name": …, "activated": true, "deployment_id": …}
activate_modelSwitch model (모델 전환); sent by the Models tabSwitches to a cached version without downloading{"name": …, "version": …}
remove_modelRemove cached model (모델 캐시 삭제); sent by the Models tabRemoves that version from the cache; fails while it is running{"removed": true}
set_policy(automatic on policy save)Applies the new policy{"applied": true}

A command that is not picked up within 24 hours (the default), or picked up and not answered within 24 hours, becomes Expired (만료). While the agent is running, a command delivered again is still executed only once. The three model commands are described in Models and inference.

Restart means exit code 3

The agent does not re-execute itself. A misbehaving process is not trusted to repair itself. On restart it stops the transfer in progress, returns the claimed queue items and ends with exit code 3, and systemd (Restart=always) or the container runtime (restart: unless-stopped) starts a clean new process. The Restart (재시작) button at the top right of the device detail page sends the same command.

Log and exit code:

WARNING geo_mlops_sdk.edge.runtime: restart requested: command 1a1d2559-…
$ echo $?
3
Exit codeMeaning
0Stopped on request (SIGTERM, Ctrl-C)
3Restart requested — the supervisor must start it again
4Could not open the local API (port in use and so on) — a config problem that restarting will not fix

Offline block

The Offline (Offline) button on the device detail page is a server-side switch, not a command. While it is on, every call made with that device's token is rejected with 503 (Retry-After: 60). The health check (/api/v1/health) is not blocked, so the device's link.state stays online and the log shows 503 edge device … is blocked by an operator. The uploader treats a 503 as a temporary failure and retries each item at growing intervals (from 10 seconds up to 15 minutes); when the block is lifted it uploads the backlog. If the block lasts more than 3 hours, however, items that have failed 20 times turn failed. After lifting the block, check with geo-mlops-edge queue --state failed and send the Resync (재동기화) command. Unlike revoking the token, you can undo it right from the screen.

Policy

A policy sets, per device and from Central, the heartbeat interval, the command poll interval, retention limits and upload throttling (retention, sync). Changing it needs the SettingsADMIN permission.

  1. Open the Policy (정책) tab on the device detail page. ① The current revision is shown. Edit the values and ② press Save policy (정책 저장).
    Policy tab — ① current revision ② Save policy (the revision goes up and the device picks it up on its next heartbeat)
  2. Saving raises the revision by 1 and also queues a set_policy command so the change applies right away. The device also fetches the new policy when it sees that policy_revision in the heartbeat response has changed.
Screen fieldSetting key
Heartbeat interval (s) (하트비트 주기 (초))heartbeat_interval_s
Retention period (days) (보존 기간 (일))retention.max_age_days
Retention size (GiB) (보존 용량 (GiB))retention.max_bytes
Upload rate limit (B/s) (전송 속도 상한 (B/s))sync.max_bytes_per_s
CPU pause threshold (%) (CPU 일시정지 임계 (%))sync.cpu_pause_percent
Allowed upload windows (전송 허용 시간대)sync.windows

These six are the fields you edit on the screen. The rest (command poll interval, minimum free disk, batch size, chunk size, concurrency, urgent priority threshold) are shown read-only below them; to change those, use the PUT /api/v1/edge/devices/{id}/policy API.

The heartbeat interval must be well below the server's offline threshold (180 seconds by default). If it is too long, a healthy device flickers to Unhealthy (비정상).

The agent is built to expect pulled cables, power cuts and days offline.

A site that runs in two steps. In STEP 1 the field PC inside the mobile control cabinet takes data from the robot arm and camera with no network, gives verdicts right away and keeps the data in local storage. After work it connects to the network on a set schedule; in STEP 2 it sends the stored data to the central server, most important first, and receives new AI models, instructions and policy. Then it goes back to the site

  1. Collection never stops. Collectors write to the local queue (SQLite + file spool) regardless of link state.
  2. It buffers within limits. It keeps to the three retention limits (max_bytes 50 GiB, max_age_days 30 days, free_disk_min_bytes 5 GiB). Items past the age limit are dropped regardless of priority; when size or free disk runs short it drops the lowest-priority, oldest items first. Items being sent are never dropped. The number dropped goes up in the heartbeat's evicted_24h and shows as a red −N in the Backlog (대기) column of the fleet list — a sign that data is piling up faster than it is sent.
  3. When the link comes back, it sends right away. After two connection checks in a row (link.online_after_ok) it registers → sends a heartbeat immediately → drains the queue. It sends the highest priority first.
  4. Nothing is stored twice. The record id is an idempotency key, so if a response is lost and the same batch is sent again, Central counts them as duplicates and stores them once. Files resume upload chunk by chunk.

When the device's CPU usage reaches cpu_pause_percent (default 85), uploads pause and items stay in the queue. When usage drops or the limit is raised, the queued items are sent. While paused, the state looks like this.

"sync":    { "state": "paused", "last_error": "paused: cpu above threshold" },
"backlog": { "count": 7, "bytes": 1150, "by_kind": { "blob": 1, "http": 3, "robot": 3 } }

The values that throttle uploads are in the sync table of the Configuration reference. Check items folded into failure with geo-mlops-edge queue --state failed, and send them again with the Resync (재동기화) command or POST /api/v1/sync:retry-failed.

Written for the platform as of 2026-10-02.

© MLOps Central Platform