Edge SDK API
Public API of geo-mlops-sdk — generated from the package
The public API of geo-mlops-sdk 0.2.0, generated from the package signatures and docstrings.
Read the Edge SDK chapter first for how to use it.
CentralClient — central server client
An async client that calls the central server's edge API (/api/v1/edge) with a device token. Use it with async with, or call aclose() when done.
CentralClient(base_url: str, token: str = '', *, timeout: float = 10.0, retry: RetryPolicy = RetryPolicy(attempts=3, initial_backoff_s=0.5, max_backoff_s=30.0, multiplier=2.0, jitter=0.25), verify: bool = True, transport: Optional[httpx.AsyncBaseTransport] = None, user_agent: Optional[str] = None) -> None
HTTP client bound to one Central deployment and one device token.
set_token
def set_token(token: str) -> None
Adopt a rotated token without rebuilding the connection pool.
aclose
async def aclose() -> None
health
async def health() -> dict
Liveness probe. Never retried -- the caller is the retry loop.
register
async def register(*, os: Optional[str] = None, sdk_version: Optional[str] = None, location: Optional[str] = None) -> RegisterResult
Self-register this device (IF-E1).
send_heartbeat
async def send_heartbeat(body: HeartbeatBody, *, retry: Optional[RetryPolicy] = None) -> HeartbeatResult
Report resources and runtime status (IF-E2).
list_models
async def list_models() -> ModelListResult
Models this device's tenant has registered (IF-E6).
model_versions
async def model_versions(name: str) -> ModelVersionsResult
Version history of one model (IF-E6).
resolve_container
async def resolve_container(model: str, version: str) -> ContainerRef
Registry reference for a model version's serving image (IF-E5).
send_records
async def send_records(records: Sequence[Record]) -> BatchResult
Hand over a telemetry batch (IF-E3).
send_inference
async def send_inference(records: Sequence[InferenceRecord]) -> BatchResult
Hand over an inference-result batch (IF-E4). Same idempotency rule.
upload_init
async def upload_init(request: UploadInit) -> UploadCreated
Open a resumable transfer.
upload_chunk
async def upload_chunk(upload_id: str, index: int, data: bytes) -> ChunkAccepted
Send one chunk. Re-sending an index already stored is a no-op.
upload_status
async def upload_status(upload_id: str) -> UploadStatus
Where a restarted transfer should pick up.
upload_complete
async def upload_complete(upload_id: str) -> UploadStatus
Close the transfer. Assembly happens server-side, so poll the status.
poll_commands
async def poll_commands(wait_s: float = 25.0) -> CommandList
Long poll for commands.
ack_command
async def ack_command(command_id: str, ack: CommandAck) -> CommandAckResult
Report what happened to one command.
fetch_policy
async def fetch_policy() -> DevicePolicy
Retrieve the policy in force for this device.
download_model
async def download_model(name: str, version: str, dest: Union[str, Path], *, progress: Optional[ProgressCallback] = None, retry: Optional[RetryPolicy] = None) -> Path
Stream a model version's artifact to dest (IF-E6).
Errors
Every error derives from SdkError. Only 429, 5xx and transport errors are retried.
| Exception | Base | Description |
|---|---|---|
SdkError | Exception | Base class for every error raised by this package. |
OfflineError | SdkError | The request never got an answer (DNS, refused, reset, timeout). |
ApiError | SdkError | Central answered with a non-2xx status. |
AuthError | ApiError | 401 -- the device token is unknown, expired or revoked. |
ForbiddenError | ApiError | 403 -- the token is valid but lacks the scope for this call. |
NotFoundError | ApiError | 404. |
ConflictError | ApiError | 409 -- e.g. completing an upload whose chunks are not all in. |
PayloadTooLargeError | ApiError | 413 -- the body exceeds a server or proxy ceiling. Retrying cannot help. |
UnprocessableError | ApiError | 422 -- the body did not validate. |
RateLimitedError | ApiError | 429 -- back off, honouring Retry-After when present. |
ServerError | ApiError | 5xx -- Central's problem, and worth retrying. |
Retry policy
RetryPolicy(attempts: int = 3, initial_backoff_s: float = 0.5, max_backoff_s: float = 30.0, multiplier: float = 2.0, jitter: float = 0.25) -> None
Exponential backoff with jitter.
Contract models (requests and responses)
Pydantic models exchanged with the central server. Unknown fields are ignored, so new server fields never break the client.
Record
One structured observation.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
kind | str | (required) | |
ts | datetime | (required) | |
priority | int | 50 | |
payload | dict[str, Any] | {} |
RecordBatch
Request body of POST /api/v1/edge/telemetry.
| Field | Type | Default | Description |
|---|---|---|---|
records | list[Record] | [] |
RejectedRecord
One record Central refused, with the reason it refused it.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
reason | str | (required) |
BatchResult
Response to a telemetry or inference batch.
| Field | Type | Default | Description |
|---|---|---|---|
accepted | int | 0 | |
duplicates | int | 0 | |
rejected | list[RejectedRecord] | [] |
UploadInit
Request body of POST /api/v1/edge/uploads.
| Field | Type | Default | Description |
|---|---|---|---|
filename | str | (required) | |
size | int | (required) | |
sha256 | str | (required) | |
chunk_size | int | (required) | |
kind | str | blob | |
dataset_id | str | None | None | |
meta | dict[str, Any] | {} |
UploadCreated
Response to upload init.
| Field | Type | Default | Description |
|---|---|---|---|
upload_id | str | (required) | |
chunk_size | int | (required) | |
received | list[int] | [] |
ChunkAccepted
Response to a chunk PUT: the indices the server now holds.
| Field | Type | Default | Description |
|---|---|---|---|
received | list[int] | [] |
UploadStatus
Response to GET /api/v1/edge/uploads/{id} -- the resume point.
| Field | Type | Default | Description |
|---|---|---|---|
upload_id | str | (required) | |
state | UploadState | uploading | |
received | list[int] | [] | |
size | int | 0 | |
chunk_size | int | 0 | |
storage_uri | str | None | None | |
error | str | None | None |
Detection
One detected instance.
| Field | Type | Default | Description |
|---|---|---|---|
cls | int | (required) | |
name | str | "" | |
conf | float | 0.0 | |
bbox | list[float] | [] | |
polygon | list[list[float]] | [] |
InferenceOutput
Result of one predict call.
| Field | Type | Default | Description |
|---|---|---|---|
task | str | "" | |
width | int | 0 | |
height | int | 0 | |
detections | list[Detection] | [] |
ModelRef
Registry coordinates of the model that produced a result.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | (required) | |
version | str | (required) |
InferenceRecord
One inference result queued for Central (IF-E4).
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
ts | datetime | (required) | |
model | ModelRef | (required) | |
input_ref | str | None | None | |
output | dict[str, Any] | {} | |
latency_ms | float | 0.0 | |
priority | int | 50 |
InferenceBatch
Request body of POST /api/v1/edge/inference.
| Field | Type | Default | Description |
|---|---|---|---|
records | list[InferenceRecord] | [] |
RegisterRequest
Request body of POST /api/v1/edge/register (IF-E1).
| Field | Type | Default | Description |
|---|---|---|---|
os | str | (required) | |
sdk_version | str | (required) | |
location | str | None | None |
RegisterResult
Response to registration.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
status | str | ACTIVE |
BacklogStatus
What is waiting in the local queue.
| Field | Type | Default | Description |
|---|---|---|---|
count | int | 0 | |
bytes | int | 0 | |
oldest_ts | datetime | None | None | |
evicted_24h | int | 0 | |
by_kind | dict[str, int] | {} |
SyncStatus
Uploader state as reported to the fleet.
| Field | Type | Default | Description |
|---|---|---|---|
state | SyncState | idle | |
last_ok_at | datetime | None | None | |
last_error | str | None | None | |
rate_bps | float | 0.0 | |
in_flight | int | 0 | |
denied | str | None | None |
ModelStatus
One model present in the local cache.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | (required) | |
version | str | (required) | |
framework | str | "" | |
active | bool | False |
CollectorStatus
One configured collector.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | (required) | |
type | str | "" | |
state | str | stopped | |
last_ts | datetime | None | None | |
error | str | None | None |
ContainerStatus
A container the edge reports running (populated by the host app).
| Field | Type | Default | Description |
|---|---|---|---|
image | str | (required) | |
version | str | None | None | |
health | str | None | None |
HeartbeatPayload
Free-form half of the heartbeat, given a shape by this SDK.
| Field | Type | Default | Description |
|---|---|---|---|
agent_version | str | "" | |
os | str | "" | |
uptime_s | float | 0.0 | |
policy_revision | int | 0 | |
backlog | BacklogStatus | ||
sync | SyncStatus | ||
models | list[ModelStatus] | [] | |
collectors | list[CollectorStatus] | [] | |
containers | list[ContainerStatus] | None | None |
HeartbeatBody
Request body of POST /api/v1/edge/heartbeat (IF-E2).
| Field | Type | Default | Description |
|---|---|---|---|
cpu | float | 0.0 | |
gpu | float | None | None | |
mem | float | 0.0 | |
disk | float | 0.0 | |
payload | HeartbeatPayload |
HeartbeatResult
Response to a heartbeat.
| Field | Type | Default | Description |
|---|---|---|---|
ok | bool | True | |
policy_revision | int | 0 |
RetentionPolicy
Local storage ceiling. Whichever bound trips first wins.
| Field | Type | Default | Description |
|---|---|---|---|
max_bytes | int | 53687091200 | |
max_age_days | int | 30 | |
free_disk_min_bytes | int | 5368709120 |
SyncPolicy
How aggressively the uploader may work.
| Field | Type | Default | Description |
|---|---|---|---|
batch_size | int | 500 | |
chunk_bytes | int | 33554432 | |
max_bytes_per_s | int | 0 | |
cpu_pause_percent | float | 85.0 | |
windows | list[str] | [] | |
concurrency | int | 1 | |
urgent_priority | int | 90 |
DevicePolicy
Response to GET /api/v1/edge/config.
| Field | Type | Default | Description |
|---|---|---|---|
revision | int | 0 | |
heartbeat_interval_s | float | 30.0 | |
commands_poll_s | float | 25.0 | |
retention | RetentionPolicy | ||
sync | SyncPolicy |
Command
One queued command.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
type | str | (required) | |
args | dict[str, Any] | {} | |
created_at | datetime | None | None |
CommandList
Response to GET /api/v1/edge/commands (empty when the wait elapsed).
| Field | Type | Default | Description |
|---|---|---|---|
items | list[Command] | [] |
CommandAck
Request body of POST /api/v1/edge/commands/{id}:ack.
| Field | Type | Default | Description |
|---|---|---|---|
status | AckStatus | ok | |
result | dict[str, Any] | None | None |
CommandAckResult
Response to an ack.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | (required) | |
state | str | "" |
ModelInfo
One registered model.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | (required) | |
stages | dict[str, str] | {} | |
tags | dict[str, str] | {} |
ModelListResult
Response to GET /api/v1/edge/models.
| Field | Type | Default | Description |
|---|---|---|---|
items | list[ModelInfo] | [] | |
available | bool | False |
ModelVersionInfo
One version of a model.
| Field | Type | Default | Description |
|---|---|---|---|
version | str | (required) | |
stage | str | "" | |
status | str | "" | |
run_id | str | "" | |
creation_timestamp | int | 0 |
ModelVersionsResult
Response to GET /api/v1/edge/models/{name}/versions.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | (required) | |
versions | list[ModelVersionInfo] | [] |
ContainerRef
Response to GET /api/v1/edge/containers/pull (IF-E5).
| Field | Type | Default | Description |
|---|---|---|---|
image | str | (required) | |
model | str | "" | |
version | str | "" |
EdgeSettings — agent configuration
The structure of the YAML configuration file. Precedence is environment > file > defaults; environment variables take the GEO_EDGE_ prefix and join levels with __ — e.g. central.token → GEO_EDGE_CENTRAL__TOKEN.
EdgeSettings
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
central | CentralSettings | GEO_EDGE_CENTRAL | ||
device | DeviceSettings | GEO_EDGE_DEVICE | ||
data_dir | Path | PosixPath('/var/lib/geo-mlops-edge') | GEO_EDGE_DATA_DIR | |
disk_path | str | "" | GEO_EDGE_DISK_PATH | |
retention | SizedRetentionPolicy | GEO_EDGE_RETENTION | ||
sync | SizedSyncPolicy | GEO_EDGE_SYNC | ||
link | LinkSettings | GEO_EDGE_LINK | ||
heartbeat_interval_s | float | 30.0 | GEO_EDGE_HEARTBEAT_INTERVAL_S | |
commands_poll_s | float | 25.0 | GEO_EDGE_COMMANDS_POLL_S | |
api | ApiSettings | GEO_EDGE_API | ||
collectors | list[CollectorSettings] | [] | GEO_EDGE_COLLECTORS | |
models | ModelSettings | GEO_EDGE_MODELS | ||
policy_source | str | central | GEO_EDGE_POLICY_SOURCE | |
log_level | str | INFO | GEO_EDGE_LOG_LEVEL |
central (CentralSettings)
How to reach the platform.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
base_url | str | "" | GEO_EDGE_CENTRAL__BASE_URL | |
token | str | "" | GEO_EDGE_CENTRAL__TOKEN | |
timeout_s | float | 10.0 | GEO_EDGE_CENTRAL__TIMEOUT_S | |
verify_tls | bool | True | GEO_EDGE_CENTRAL__VERIFY_TLS |
device (DeviceSettings)
Identity overrides. Empty id means "use the hostname".
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
id | str | "" | GEO_EDGE_DEVICE__ID | |
location | Optional[str] | None | GEO_EDGE_DEVICE__LOCATION |
retention (SizedRetentionPolicy)
Retention with human-readable sizes accepted from YAML.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
max_bytes | int | 53687091200 | GEO_EDGE_RETENTION__MAX_BYTES | |
max_age_days | int | 30 | GEO_EDGE_RETENTION__MAX_AGE_DAYS | |
free_disk_min_bytes | int | 5368709120 | GEO_EDGE_RETENTION__FREE_DISK_MIN_BYTES |
sync (SizedSyncPolicy)
Sync policy with human-readable sizes accepted from YAML.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
batch_size | int | 500 | GEO_EDGE_SYNC__BATCH_SIZE | |
chunk_bytes | int | 33554432 | GEO_EDGE_SYNC__CHUNK_BYTES | |
max_bytes_per_s | int | 0 | GEO_EDGE_SYNC__MAX_BYTES_PER_S | |
cpu_pause_percent | float | 85.0 | GEO_EDGE_SYNC__CPU_PAUSE_PERCENT | |
windows | list[str] | [] | GEO_EDGE_SYNC__WINDOWS | |
concurrency | int | 1 | GEO_EDGE_SYNC__CONCURRENCY | |
urgent_priority | int | 90 | GEO_EDGE_SYNC__URGENT_PRIORITY |
link (LinkSettings)
Connectivity probing.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
probe_interval_s | float | 5.0 | GEO_EDGE_LINK__PROBE_INTERVAL_S | |
backoff_max_s | float | 60.0 | GEO_EDGE_LINK__BACKOFF_MAX_S | |
online_after_ok | int | 2 | GEO_EDGE_LINK__ONLINE_AFTER_OK | |
offline_after_fail | int | 3 | GEO_EDGE_LINK__OFFLINE_AFTER_FAIL |
api (ApiSettings)
Local HTTP surface for the on-site UI.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
enabled | bool | True | GEO_EDGE_API__ENABLED | |
host | str | 0.0.0.0 | GEO_EDGE_API__HOST | |
port | int | 8600 | GEO_EDGE_API__PORT | |
token | str | "" | GEO_EDGE_API__TOKEN | |
cors_origins | list[str] | ['*'] | GEO_EDGE_API__CORS_ORIGINS | |
max_body_bytes | int | 2147483648 | GEO_EDGE_API__MAX_BODY_BYTES |
collectors (CollectorSettings)
One configured collector. Type-specific keys stay in options.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
type | str | (required) | GEO_EDGE_COLLECTORS__TYPE | |
name | str | "" | GEO_EDGE_COLLECTORS__NAME | |
enabled | bool | True | GEO_EDGE_COLLECTORS__ENABLED | |
priority | int | 50 | GEO_EDGE_COLLECTORS__PRIORITY | |
options | dict[str, Any] | {} | GEO_EDGE_COLLECTORS__OPTIONS |
models (ModelSettings)
Local model cache behaviour.
| Field | Type | Default | Description | Environment variable |
|---|---|---|---|---|
auto_activate | str | Production | GEO_EDGE_MODELS__AUTO_ACTIVATE | |
keep_versions | int | 2 | GEO_EDGE_MODELS__KEEP_VERSIONS |
Extension points
Protocols and functions for registering your own collectors and inference runners.
Sink
What a collector is handed to publish through.
async def record(kind: str, payload: dict, *, priority: int = 50, ts: Optional[datetime] = None, meta: Optional[dict] = None, record_id: str = '') -> Any
async def blob(kind: str, source: Union[str, Path, bytes], *, filename: str = '', priority: int = 50, ts: Optional[datetime] = None, meta: Optional[dict] = None, move: bool = False) -> Any
Collector
A source of data attached to this edge.
async def start(sink: Sink) -> None
async def stop() -> None
def status() -> CollectorStatus
register_collector
def register_collector(type_: str, factory: CollectorFactory) -> None
Make type_ usable in configuration.
build_collector
def build_collector(type_: str, name: str, *, priority: int = 50, options: Optional[dict] = None) -> Collector
Instantiate one configured collector.
Runner
Loads one model and answers predictions for it.
def load(model: LocalModel) -> None
def predict(image: bytes, **params) -> InferenceOutput
def close() -> None
register_runner
def register_runner(framework: str, factory: Callable[[], Runner]) -> None
Teach the SDK about a framework it does not ship support for.