ados.sdk. The other option is the
ados-sdk crate; both speak the same
length-prefixed msgpack wire and capability-token handshake to the
plugin host. Python suits a plugin that leans on the Python ecosystem
(inference, scripting, fast hardware bring-up); Rust suits a tight,
long-running service.
A Python agent half runs in its own systemd unit, started by the plugin
runner. Import the author surface from ados.sdk, not from internal
agent modules.
Install
There is no PyPI package. Develop against a checkout ofaltnautica/ADOSDroneAgent
installed in your environment (pip install -e . in the checkout) so
import ados.sdk resolves. On a node, the runner provides the same
package.
What ados.sdk exports
- Driver layer. The base classes hardware-driver plugins subclass, plus the dataclasses they exchange with the host. See the driver layer.
- Vision.
VisionClientand the frame, detection and model types a plugin uses to read frames and publish detections. - Camera selection. Helpers that resolve a camera parameter (a
camera id or
auto) to the camera the plugin should use. - Offload gates and lock tracking. The freshness and lock gates and
LockedTargetTrackerthat a behavior plugin uses to act only on a fresh, locked target. - Testing.
PluginTestHarness,FakeVisionEngineandload_fixtureexercise a plugin in-process with no agent.
ados.sdk does not export a context class. The runner hands ctx to
your hooks at call time; a plugin that wants static typing declares a
local Protocol for the parts of ctx it uses, as the reference
extensions do.
The agent-half plugin shape
An agent half is a plain Python class with no base class. The manifest’sagent.entrypoint points the runner at it:
module:Class, for code packaged as an importable module (follow_me:FollowMePlugin).- A path inside the archive (
agent/plugin.py), in which case the class must be namedPlugin.
on_install, on_enable, on_configure(ctx, config),
on_start, then the runner waits for shutdown, then on_stop and
on_disable. See Lifecycle for when each runs.
The plugin context
Every facade call is gated on a capability; a call whose capability was not granted is rejected withcapability_denied: <cap>.
A real skeleton
This is the Follow-Me reference plugin, trimmed to its lifecycle shape. Each subscription matches a manifest permission (mavlink.read,
event.subscribe, vision.detection.subscribe).
altnautica/ADOSExtensions
under extensions/follow-me/.
IPC
The unit passes the Unix socket path inADOS_PLUGIN_SOCKET and the
node profile in ADOS_NODE_PROFILE. The token, the bound agent id and
the data dir arrive in a systemd credential at
$CREDENTIALS_DIRECTORY/ados-plugin-token, never in the environment;
the runner reads it for you. If the socket or the credential is not
there yet, the runner keeps retrying until the plugin host accepts the
connection. It then speaks msgpack RPC:
Resource limits
The plugin host enforces the manifest’s resource block:MemoryMax, CPUQuota and TasksMax on the
plugin’s unit in ados-plugins.slice. An OOM kill ends the process and
systemd restarts it after 2 s, with no start limit.
Testing
PluginTestHarness wires a real plugin context to fake host stubs, so a
pytest run drives your hooks with no agent and no hardware:
- exposes
harness.context, the context to pass to your hooks; - delivers events with
await harness.publish_event(topic, payload)and captures the plugin’s output withharness.published_events(), a list of(topic, payload)tuples; - replays recorded scenarios with
await harness.replay_fixture(name_or_path)(load files withload_fixture); - grants and revokes capabilities with
harness.grant(...)andharness.revoke(...).
FakeVisionEngine stands in for the vision engine and pushes synthetic
frames into a VisionClient. ados plugin test <dir> runs a plugin’s
pytest suite with the manifest validated first; see the
Plugin CLI reference.
Where the rest of the contract lives
src/ados/plugins/manifest.py: the strict manifest model the CLI’slint,signandtestenforce.src/ados/plugins/runner.py: the process entrypoint that loads a plugin and calls its hooks.crates/ados-plugin-host/src/{signing,state,supervisor,archive}.rs: signature verification and the revocation list, persistent install and grant state, the install and enable lifecycle, and archive unpacking with traversal protection.
Next steps
Your first plugin
Build, sign and install a plugin end to end.
Event hooks and bus
Topics and the agent event bus.
Vision plugins
Frames, models and detections.
Rust SDK
The same surface in Rust.