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:
| Effect | The operation |
|---|---|
| Memory allocation | Takes memory from a heap. |
| Blocking | Waits without letting other work run. |
| Network | Opens or uses a network connection. |
| Remote call | Calls a service on another machine. |
| Model call | Sends a request to a model. |
| Storage | Reads or writes files or other stored data. |
| Clock | Reads the time. |
| Device access | Uses a peripheral of the board or machine. |
| Spawning | Starts 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:
| Code | Restriction |
|---|---|
| Configuration | No effects while it is read: no files, network, models or storage. |
| Edge mappings | Deterministic: no model calls, tools, network or storage. That work belongs in a node. |
| Hooks | Only the effects their target allows. |
| Real-time control paths | No model calls, no unbounded memory allocation and no blocking operations, however indirectly. |
| The smallest boards | No heap at all. |
| Edge mappings, hooks, configuration records, global functions and reusable functions | No 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 component | No 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,
mainand 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.