Isolated components
In AEL, the Agent Engineering Language, 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. Honest limits says what happens on any other host.
The isolated modifier
isolated comes before the keyword of the declaration:
# src/billing.agent.ael
isolated agent billing(invoice: Invoice) -> Receipt {
config {
nodes: [totaler = total_invoice];
starts: [totaler];
completion: totaler.result;
}
}
# src/nodes/scrub.node.ael
isolated node scrub(record: Str<4000>) -> Str<4000> {
return remove_secrets(record);
}
fn remove_secrets(record: Str<4000>) -> Str<4000> {
# Your rules for what may leave the record.
}
# src/issue_reader.subagent.ael
isolated subagent issue_reader(issue: u64) -> u64 {
config {
nodes: [parser = parse_issue];
starts: [parser];
completion: parser.result;
}
}
- The modifier is part of the declaration. It is neither a hook attribute nor a configuration field, so no configuration can set it or remove it.
- The file keeps its name:
billing.agent.ael,scrub.node.ael,issue_reader.subagent.ael. - Only an agent, a node or a subagent takes the modifier. The check refuses
isolatedbeforemain, a global or reusable function, a hook, a configuration, an edge or any other role. - The body of
remove_secretsis a placeholder, as A first agent explains.
What isolation gives
| Aspect | An isolated component |
|---|---|
| Where it runs | Always in a sandbox, in its own process. |
| Who reaches it | Only the edges declared to it. It is outside the shared communication layer, so nothing else can call it or send it a value. |
| What it holds | Only the bindings it declares itself: nothing inherited from the agent around it and nothing granted to it through a spawn or an edge. |
| What ends it | A cancellation or its deadline, either of which ends its process. |
Reached only through its edges
When an agent reaches an isolated node through one edge, only that agent, through that edge, communicates with the node. No other agent, node or subagent reaches it, and the node reaches nothing except through its own declared edges.
# src/intake.agent.ael
agent intake(request: Request) -> Reply {
config {
nodes: [reader = read_request, scrubber = scrub, answerer = answer];
edges: [read_to_scrub(reader, scrubber), scrub_to_answer(scrubber, answerer)];
starts: [reader];
completion: answerer.result;
}
}
Here scrub is the isolated node above: read_to_scrub carries a record to it, scrub_to_answer carries its result on, and nothing else in the program reaches it. Every edge is a typed, two-way channel: AEL generates the communication between nodes, agents and subagents from your edge declarations, with no client or server code for you to write. The edges of an isolated component are generated in the same way; see Communication between agents.
What the check refuses
The check refuses every one of these when you check your code, with a diagnostic that points at your source:
- Ambient tools, files or network. An isolated component calls no tool, opens no network connection and reaches no file outside its own private directory.
- A model or tool call of its own. It makes no model or tool call itself: it reaches one through a declared edge to a node that is not isolated.
- A function in another language on the same machine. A function in another language runs inside an isolated component only in sandbox mode; see Sandbox mode and isolated components.
- A subagent that is not isolated. Inside an isolated component,
spawnstarts only isolated subagents; see Isolated subagents. - A binding from outside. A binding inherited from the agent around it, or passed in through a spawn or an edge, is refused.
- A hook with an ambient effect. A hook attached to an isolated component runs inside the same boundary and holds no ambient effect.
Its own bindings
An agent, subagent or node declares the memory, skills, knowledge, storage and database it uses, each bound to a package you select, and the check refuses any use it did not declare. An isolated component holds exactly the bindings it declares in its own declaration, and no other. Bindings describes the record.
Cancellation and deadlines
- Cancelling an isolated component, or reaching its deadline, ends its process and removes its private directory.
- What it spends counts against the budget of the agent around it, as for any child; see Budgets, retries and validation.
- An effect outside the program whose outcome is not known stays unknown, for your code to reconcile.
Permissions are not a sandbox
Effects and capabilities keep your own code from doing what it has not been allowed to do. They are not a sandbox: when a component must run in one, mark it isolated. Code in another language has a sandbox mode of its own, which Sandbox mode and isolated components describes.
Honest limits
- Isolation needs the isolation facilities of Linux and runs only on the Linux target the documentation names for it: on macOS, on Windows, on microcontroller boards, on other Linux targets and on any host without those facilities, an isolated component is refused, never run without isolation. Supported targets gives the exact target.
- An isolated component reaches models, tools and the network only through its edges, so a component that needs them directly is not isolated.
Related
- Subagents: agents spawned at run time, isolated or not.
- Communication between agents: the edges that reach an isolated component.
- Bindings and storage: the bindings an isolated component declares.
- Functions in other languages: code in other languages, and its sandbox mode.