OPAL (Operator Permission and Access Layer) is the single command surface every operator — you, an automation rule, or a connected language model — uses to make OctoMY™ do something.
The one-sentence version
Every operation in OctoMY™ that does something — capture a screenshot, pair with a robot, list mounted hives, run a diagnostic, flash firmware — is wrapped as an OPAL Task. The same task runs the same way whether you click it, schedule it, or an LLM invokes it; only the permission check changes.
OctoMY™ is built around a hard separation between the embedded layer (real-time motor and sensor control, where mistakes are dangerous) and the strategic layer (high-level intent: "drive to the workshop, pick up the box"). See the Embedded-Strategic Barrier for the full architectural background.
OPAL is the strategic layer's interface to the embedded layer. Two consequences fall out of this:
OpalTask with the same code path. There is no "automation API" that diverges from "what the UI does."| Piece | What it is |
|---|---|
| OpalTask | One unit of work. Declares its name, parameters, required permissions, execution hints (timeout, idempotent, can-be-skipped), and the keys of the values it produces. |
| OpalTaskRegistry | The catalog of every task the running app knows about. Tasks are registered by domain (catalog, navigation, screenshot, batch, …). |
| TaskPlan | An ordered list of task invocations, serialisable to JSON. Steps can pass values to subsequent steps via output keys. The unit a plan author / LLM composes. |
| OpalTaskRuntime | The executor. Runs a TaskPlan step by step on a background thread, enforces permissions, reports progress, and records the outcome to the history database. |
A Task is to a button what a TaskPlan is to a workflow.
Every task invocation carries an operator type. The runtime checks permissions differently for each, but the task itself doesn't care who called it.
| Operator | Permission check | Example |
|---|---|---|
| Sentient (you) | None — you're the device's authority | You click "Pair via QR" in the Hub |
| Automation (trigger / directive) | Pre-approved at the time the rule was created | A schedule fires "Capture all widgets" every Monday |
| LLM | Live check against the model's granted scopes; unknown scopes prompt for approval | An LLM chats "list my robots", which resolves to node.list |
The same node.list task in all three cases. The same code. Different gate.
Each task declares the permission scope it needs (e.g. catalog.capture, node.create, filesystem.write). The operator's grants are checked at execution time:
filesystem.write?") that you can accept once or for the whole conversation.Every execution — successful, failed, or denied — lands in OpalHistoryDatabase, visible in the OPAL History activity. So you can always see exactly what was done, by whom, against which Sentient and Node, with what parameters, and what came out.
A single task does one thing. A TaskPlan is a JSON document chaining several:
{
"steps": [
{"task": "catalog.list_by_tag", "tag": "trust"},
{"task": "catalog.capture", "id": "$1.results[0].id"},
{"task": "filesystem.copy", "from": "$2.image_path", "to": "/exports/"}
]
}
Outputs of one step are addressable by the next ($1.results[0].id). This is the surface LLMs use to express multi-step intent, and what the app uses internally for batch jobs and triggers.
Each subsystem registers its own tasks into the central registry. The domains that exist today:
| Domain | What it controls |
|---|---|
| Catalog | Browse and capture widgets (the widget catalog system) |
| Navigation | List and open activities in the running app |
| Screenshot | Take a screenshot of the screen or a widget |
| Batch | List, query, and cancel background jobs |
| Filesystem | Sandbox-restricted file operations |
| Directives | Create, list, pause, resume, and delete trigger directives |
| Constellation | Manage your node constellation — list, create, launch, stop |
| Help | Search, list, outline, read, and open documentation pages |
| Serial | Manage serial connections (list ports, open, close, configure) |
| BanterLab | Drive the BanterLab parameter / codec / testset workflow |
| Shade | Run LLVM-compiled compute shaders |
| Sentient | Create / delete / select Nodes, set Sentient password, export recovery |
| Construct | Edit a Construct scene (add / remove / rename items, set transforms) |
See the OPAL reference for the per-task catalogue.
| UI surface | What it shows |
|---|---|
| OPAL activity | Direct task explorer — pick a task, fill its parameters, run it. The "developer's REPL" for the app. |
| OPAL History activity | Audit log: every task that ever ran on this Sentient, parameters, outcome, who invoked it |
| Sentient Permissions activity | Per-LLM grant list — which scopes each model has, accept/revoke individually |
| BatchActivity | Long-running OPAL Tasks that report progress show up here |
| Directives activity | Trigger rules that fire OPAL Task plans on a schedule or condition |
| LLM chat overlay | Every assistant action is one or more OPAL Tasks — you see the names in the conversation transcript |
Can I write my own task? Yes — see the internal developer documentation. A task is a C++ class with a name, a parameter list, a permission scope, and an execute() method. Once registered in any of the Register<Domain>Tasks files, it's available to every operator.
Are tasks stable across versions? Task names and parameter shapes are part of the public surface and follow semantic versioning. Renames go through a deprecation window with an alias.
Can a TaskPlan be interrupted? Yes — the runtime supports cooperative cancellation. Tasks that are interruptible (most I/O-bound work) can be cancelled mid-execution; CPU-bound tasks finish their current step before stopping.
Does OPAL run only on the Hub? No — every node type (Agent, Remote, Hub) has an OPAL runtime. The set of available tasks differs by node: an Agent has access to its own actuators, a Remote can drive a paired Agent, a Hub can introspect any connected node.
| Component | Role |
|---|---|
OpalTask |
Base class — name, params, permissions, hints, output keys, execute() |
OpalTaskRegistry |
Central catalog of registered tasks |
OpalTaskRuntime |
Background executor; permission enforcement; progress; cancellation |
TaskPlan |
Serialisable ordered list of task invocations |
OpalHistoryDatabase |
Audit log of every execution |
OPALActivity |
UI task explorer |
OpalHistoryActivity |
UI for the audit log |
SentientPermissionsActivity |
Per-LLM grant management |
OpalTaskBatchWorker |
Bridges long OPAL Tasks into the Batch system |