Browse the documentation

Preview documentation for AEL Beta 0.0.1 — launching soon

Agents, nodes and edges

In AEL, the Agent Engineering Language, agents, nodes (business steps) and edges (typed connections) will be first-class building blocks, each in its own named file, so a project's structure will read at a glance. This page introduces all three; the rest of this guide describes each part in detail.

Status

Planned for AEL Beta 0.0.1. AEL is not available yet.

The three building blocks

ComponentFileWhat it is
Node<name>.node.ael, declaring node <name>(…)One business step: deterministic logic, or a model call with its tools.
Edge<name>.edge.ael, declaring edge <name>(…)A typed, directed connection from one node's output to another's input, with its delivery and reply policy.
Agent<name>.agent.ael, declaring agent <name>(…)A named workflow: which nodes and edges it runs, where work starts and what completes it.

Each file will hold exactly one primary declaration, whose name matches the file name, plus private helper functions. Files and roles gives the rules for every file role.

A node

A node will take a typed input and return a typed output. This one will ask a model for a summary, following a system prompt:

Preview syntax — may change before launch
# nodes/summarize.node.ael
node summarize(input: Request) -> Summary {
    config {
        prompt: file("prompts/summarize.md");
        model: binding("primary_model");
        max_attempts: 2;
    }
    return write_summary(input);
}

fn write_summary(input: Request) -> Summary {
    # A private helper: only this node can call it.
}

Helper bodies on this page that hold only a comment are placeholders until the library's operation names are final; A first agent explains why, and how a node will call its bound model.

A node that needs no model will be ordinary code:

Preview syntax — may change before launch
# nodes/verify.node.ael
node verify(input: VerifyInput) -> Verification {
    return check_summary(input);
}

fn check_summary(input: VerifyInput) -> Verification {
    # Your own rules, such as required facts and a maximum length.
}

A node will be able to call models, tools, services, retrieval and memory, and your own functions. Declaring a node will do nothing by itself: it will make no model call and start no timer or server until a run reaches it.

An edge

An edge will carry one node's output to another node's input. Its body will map the value it receives to the input the next node expects:

Preview syntax — may change before launch
# edges/summary_to_verify.edge.ael
edge summary_to_verify(summary: Summary) -> VerifyInput {
    return VerifyInput(summary);
}
  • The mapping will be deterministic and bounded: it will select, move and convert fields. Model calls, tools and network access will belong in a node.
  • An edge will also declare how the value travels: as an event, as a request that expects a reply, with a callback, or as a stream. Workflows describes each mode.
  • How an edge names its mode, deadline and callback will be confirmed when the syntax is final.

An agent

An agent will put nodes and edges together:

Preview syntax — may change before launch
# agents/support.agent.ael
agent support(input: Request) -> Decision {
    config {
        nodes: [summarizer = summarize, verifier = verify];
        edges: [summary_to_verify(summarizer, verifier)];
        starts: [summarizer];
        completion: summary_to_verify.callback_result;
    }
}
  • nodes will name the node instances this workflow uses.
  • edges will connect them: here from summarizer to verifier.
  • starts will say where work begins. AEL will never guess a starting point from file order or from a node without incoming edges.
  • completion will say which result ends the run and becomes the agent's output.

An agent with a single node will need no edge. An agent will also be able to contain other agents; see Teams of agents.

Definitions, instances and runs

  • A definition will be what a file declares, such as the node summarize.
  • An instance will be a configured use of a definition inside an agent, such as summarizer = summarize. The same definition will be able to appear more than once under different names, each instance with its own settings: one node reading two cameras, for example.
  • A run will be one execution of an agent for one input. It will have its own run ID and budget, and its configuration will be resolved and locked into a snapshot before it starts, so settings cannot change underneath it (see Configuration).

One file per definition will never limit a project to one agent or one run at a time.

Model-driven and deterministic decisions

Each node will decide in one of two ways:

  • Model-driven: the node will have a model binding, and usually a system prompt, and a model will propose the next result or tool call.
  • Deterministic: the node will run your code on its typed input. It will need no prompt, model binding or credentials.

One workflow will mix both kinds, so it can route sensor readings or events with deterministic nodes and call a model only where one is needed, without paying for a model call at every step.

From main to an answer

The program's entry point, main, will take no parameters. It will read its input and call the agent like a function:

Preview syntax — may change before launch
# main.ael
main main() {
    let request: Request = read_request();
    let decision: Decision = support(request);
    show(decision);
}

fn read_request() -> Request {
    # A private helper that reads the request from the console.
}

fn show(decision: Decision) -> () {
    # A private helper that writes the decision to the console.
}

A console agent will need no server: it will read its input, run, and write its answer. Add the HTTP package and declare routes to make it a REST API, or remove them to go back to console-only, as Services and APIs shows. The first agent walk-through builds a console agent step by step.

What the check will refuse

  • A file whose name does not match its declaration.
  • An instance of a node or agent that does not exist.
  • An edge between a node's output and an input of a different type.
  • An agent with no starting point or no completion, and a node instance that nothing connects.
  • A node or edge that reaches a private helper of another file.