Browse the documentation

AEL 1.0.0

Effects and capabilities

In AEL, the Agent Engineering Language, compile-time effect and capability checks let code do only what it has been allowed to do. A permission mistake is caught before anything runs, with a diagnostic that shows the path to the operation that caused it.

Effects

An effect is something an operation does besides computing a value. The check tracks these kinds:

EffectThe operation
Memory allocationTakes memory from a heap.
BlockingWaits without letting other work run.
NetworkOpens or uses a network connection.
Remote callCalls a service on another machine.
Model callSends a request to a model.
StorageReads or writes files or other stored data.
ClockReads the time.
Device accessUses a peripheral of the board or machine.
SpawningStarts a subagent.

Effects follow every call. A function has the effects of everything it calls, however deep: a helper function, an imported function, a package export, a hook, an output check or a tool cannot hide one. If a call's effects are not known, the check treats them as unknown, never as none.

Where effects are restricted

Some kinds of code are allowed only some effects, and the check refuses the rest:

CodeRestriction
ConfigurationNo effects while it is read: no files, network, models or storage.
Edge mappingsDeterministic: no model calls, tools, network or storage. That work belongs in a node.
HooksOnly the effects their target allows.
Real-time control pathsNo model calls, no unbounded memory allocation and no blocking operations, however indirectly.
The smallest boardsNo heap at all.
Edge mappings, hooks, configuration records, global functions and reusable functionsNo spawning: spawn and try_spawn are allowed only in the body of an agent, a subagent, a node or main, and in their private helper functions. See Subagents.
An isolated componentNo ambient tools, files or network, no model or tool call of its own, and no function in another language that runs on the same machine outside a sandbox. It is reached only through its declared edges and holds only the bindings it declares itself, and a hook attached to it holds no ambient effect.

When the check refuses an effect, its diagnostic shows the chain of calls from your code to the operation that has the effect, so you can see where it came in.

You mark an agent, node or subagent as isolated: it always runs in a sandbox in its own process, outside the shared communication layer, reachable only through the edges you declare and holding only the resources it declares itself. Isolation needs the isolation facilities of Linux and runs only on the Linux target the documentation names for it: on any host without those facilities, an isolated component is refused, never run without isolation. A function in another language runs on the same machine by default or in a sandbox, which needs the isolation facilities of Linux and runs only on the Linux target the documentation names for it. Isolated components and Functions in other languages describe the rules.

A real-time path that passes the check is restricted to operations that suit real-time work. The check does not by itself prove that the path meets its deadline.

Capabilities

A capability is the permission to use something specific: a device, a network listener, a tool or a model binding. In AEL it is a typed value that code cannot forge, build from a number or a string, or create out of nothing.

  • Granted by composition. The code that puts your program together, main and the configuration of your agents, hands capabilities out.
  • Passed explicitly. A component receives a capability only when it is passed one, and passes it on only by an explicit transfer.
  • Never widened. Child work receives at most the permissions of the work that started it. A subagent holds only the permissions and resources that the agent that spawned it grants it, never more than that agent holds. An isolated subagent receives no grant: it holds only the bindings it declares itself, and never a storage point of its own.
  • Checked for extensions too. Hooks, output checks and tools obey the same capability checks as the rest of your code.

A capability says what code may use. Who may start a run is a separate question, checked where each request enters your program; see Services and APIs.

Prompts never grant permissions

A system prompt, a model's output or any other text cannot grant a capability, remove an effect restriction or raise a limit. A rule written in a prompt, such as a speed limit for a motor, belongs in your code as well, as a typed check at the tool that moves the motor.

Packages ask; your manifest records it

Each package in pack.ael lists the capabilities it asks for, such as "net.listen" for a package that accepts network connections. The list is a request, never a grant: the package still receives only what your code passes to it.

{ name = "server/http"; version = "^1.2.0"; kind = "runtime";
  source = { kind = "registry"; };
  features = []; targets = []; capabilities = ["net.listen"];
  publisher = "openeng"; }

Manifest reference describes the field.