uniac SDK and declare their dependencies as class-level type annotations.
| Kind | SDK base class | Purpose |
|---|---|---|
lib | uniac.Service | Reusable building block, consumed by other Services or Systems. |
app | uniac.System | Deployable composition. Each deploy targets one System. |
kind field in uniac.json selects which one applies.
Declaration shape
A Service or System is a plain Python class. Class-level annotations of typeNode declare what it depends on; __init__ initializes them.
load() constructs the instance, validates that every annotated Node slot is filled, and hydrates each Node’s .url from the deploy-time wiring. See load.
Service vs System: when to use which
- Use Service (
kind=lib) for code you want other packages to consume — a database client, a logger, a feature flag reader. Publish it withuniac build. - Use System (
kind=app) for the unit you deploy. A System pulls Services together and exposes the public surface (HTTP, jobs, scheduled work).
No magic
The framework does not auto-instantiate annotated Nodes. The annotation is a declaration; the value comes from your__init__. load() validates after construction and raises UniacValidationError if any slot is unset or holds the wrong type.
There is no base-class __init__ to call. If you don’t need init args, omit __init__ entirely.
