Browse the documentation

AEL 1.0.0

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 isolated before main, a global or reusable function, a hook, a configuration, an edge or any other role.
  • The body of remove_secrets is a placeholder, as A first agent explains.

What isolation gives

AspectAn isolated component
Where it runsAlways in a sandbox, in its own process.
Who reaches itOnly 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 holdsOnly 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 itA 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, spawn starts 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.