Skip to main content
A plugin runs on a small SBC alongside the rest of the agent. The plugin host budgets resources through systemd and the shared ados-plugins.slice cgroup. This page covers the budgets, how to spot when you blow them, and how to profile. Unit, cgroup and log names are explained on Agent runtime and sandbox.

Default budgets

When a plugin’s manifest does not declare resources, it gets: Declare different caps in the manifest:
class: heavy (first-party only) raises the ceilings to 65536 MB, 3200 % and 4096 PIDs. A third-party manifest that sets it is refused at install. Honest declarations matter. The operator sees the requested budget in the install dialog. Asking for far more than you use is a bad signal; asking for too little ends with the kernel killing your process. The caps map straight to the plugin’s unit: max_ram_mb to MemoryMax, max_cpu_percent to CPUQuota, max_pids to TasksMax.

Find the plugin’s cgroup

The unit name carries an 8-hex hash, so ask systemd for the cgroup path rather than building it:
Prefix that path with /sys/fs/cgroup in the commands below.

Spotting cgroup throttling

max_cpu_percent is enforced by the cgroup CPU controller. A plugin that breaches it does not crash; it gets throttled. The symptom is “everything got slower for no reason.”
The interesting field is nr_throttled. If it climbs every second, your plugin is over budget. Optimize the code or declare a higher max_cpu_percent.

Memory pressure

max_ram_mb is enforced by MemoryMax. A breach OOM-kills the process. The unit restarts 2 s after each kill, indefinitely, so a plugin stuck over its cap loops rather than stopping; watch oom_kill in memory.events climb.
memory.events shows low, high, max, oom and oom_kill counters. Any non-zero high or max means the kernel started applying pressure. To stay under the cap:
  • Process events on a bounded queue, not an unbounded list.
  • For ML models, prefer quantized weights (int8 over fp32).
  • Stream files; do not load whole logs into RAM.
  • Use array.array or numpy over a Python list of floats.

Inspecting a running plugin

ados plugin info <id> shows the plugin’s recorded state and granted permissions. Pair it with the cgroup counters above and the plugin’s log:
A plugin running consistently near any cap is one bad input away from a throttle stall or an OOM kill.

Profiling Python plugins

The SDK does not bundle a profiler; use cProfile or pyinstrument inside your own start path:
Plugin stdout and stderr append to the plugin’s log file, so profiler output lands there; read it with ados plugin logs <id>.

Profiling TypeScript plugins

Open Mission Control, pick the plugin’s iframe in browser devtools (Sources tab), and use the Performance recorder. The iframe is a real browsing context with the standard devtools surface. Common GCS hot paths:
  • React re-renders triggered by every telemetry event. Coalesce with requestAnimationFrame and a local ref.
  • Heavy SVG redraws. Switch to canvas past a few hundred paths.
  • Synchronous JSON parse in the message handler. Move it off the main thread.

Event-loop discipline

The biggest cause of agent-plugin stalls is a blocked event loop. A blocked loop stalls every IPC call and subscription; nothing restarts it for you. Don’t:
  • time.sleep(...) in async code.
  • Heavy CPU work directly in on_start.
  • Synchronous I/O on a slow disk.
Do:
  • await asyncio.sleep(...).
  • await asyncio.to_thread(heavy_work).
  • aiofiles or chunked reads for slow I/O.

Disk and network discipline

The plugin slice runs at a low I/O weight, so a plugin that writes hard loses every contended block to the flight services and stalls itself. A plugin writing a megabyte of samples per second to an SD card is already at the sustained-write ceiling for cheap cards. Batch writes (one fsync per second is plenty) and keep your own files bounded. Plugins with network.outbound share the drone’s link with telemetry and video. Pull large payloads during ground time and cache them.

Thermal behavior

Sustained high CPU on a small SoC raises its temperature, and the kernel eventually throttles the whole package, which shows up as throttle events on every plugin, not just yours. A well-behaved plugin watches the system telemetry and backs off before the kernel forces the issue.

Next steps

Versioning and updates

Semver, compatibility ranges and automatic updates.

Agent runtime and sandbox

Unit names, sandbox, restart policy and logs.
Last modified on October 11, 2026