AidaHL Coding Guide
AidaHL is the text language for Agent Hierarchy chips (.ahl). One class is one chip. Stack: Board > SoC > IC > Module / Agent. Language 1.4.
AI Hierarchy is the visual Hierarchy Builder canvas on the desktop. Circuit City is a separate product surface. The three are not the same thing.
Free / logged-out: this page is teach and practice only. There is no compile in the browser. Upgrade to Pro or Team — or sign in if you already have a plan.
Signed in — Free: Save/Compile is Pro/Team. This page does not compile or grade your AidaHL. Upgrade at /pricing.
Pro/Team: Save/Compile on aidaide.app goes through GET /api/ahl/entitlement and POST /api/ahl/compile (401 / 403 / 200). That is a gate, not a compiler body and not the desktop Hierarchy Builder. Lab Check/grade stays desktop teach text.
Windows ships 1.0.0-rc15 today. Coming in RC16 — not available to download yet.
Code Agent Hierarchy teams as text. Three moves make every chip: name an object, set parameters with a dot, and wire(src, dst). Practise in the AidaHL Coding Lab (25 labs / 7 tracks). Site Save/Compile is a Pro/Team entitlement gate — not a compiler body, not Lab Check/grade, and not the canvas.
On this page
- 1. Quick start
- 2. Make an object
- 3. Set parameters
- 4. Pins and ports
- 5. wire(src, dst) — two parameters
- 6. Wire layers
- 7. Packages and files
- 8. Built-in modules
- 9. Values and expressions
- 12. Inheritance and templates
- 13. Imports
- 14. Operations — run, ask, feed, pos, size
- 15. Control — when, else, retry, loop, each
- 16. Runtime conditions
- 18. What runs when
- 19. Test blocks
- 20. Recipes
- 23. Errors and Save-refuse
- 24. When a chip does nothing
- 25. Full walkthrough
- 26. Glossary
- 27. Cheat sheet
1. Quick start
AidaHL (Aida Hierarchy Language) is how you code an Agent Hierarchy chip as text. One class is one chip. On the desktop, Save + Compile (Ctrl+S) turns every class in the file into an IC, SoC, or Board; Open in Builder puts the top one on the canvas. On this website, Pro/Team may Save/Compile via GET /api/ahl/entitlement and POST /api/ahl/compile — a gate, not a compiler body and not Hierarchy Builder equivalence. Free stays teach-only.
Board > SoC > IC > Module / Agent
Three moves make every chip: name an object, set its parameters with a dot, and wire(src, dst).
class ReviewLane : IC {
in ticket : text
out report : text
var craig = Craig(Agent.claude-sonnet, Persona.ChiefArchitect);
var brian = Brian(Agent.Coder, Persona.TechLead);
craig.prompt = "Review the PR.";
brian.prompt = "Fix what the review found.";
wire(ticket, craig);
wire(craig, brian);
wire(brian, report);
}
Practise: A wire · Hello, chip
2. Make an object
Give it a name, pass an Agent and a Persona as parameters. Craig and Brian are labels: the constructor name becomes the object, and its parameters decide what it is.
var craig = Craig(Agent.claude-sonnet, Persona.ChiefArchitect);
var brian = Brian(Agent.Coder, Persona.TechLead);
var lead = Lead(Agents.ProductStrategist);
Agent.X is a portal agent or model alias. Agents.X is a catalog role. Persona.Y is a persona (and Persona.Y.Z a fork). Both catalogs bind automatically. Any other constructor name is a label; the type comes from the first Agent. argument.
Practise: An object · Name the cast
3. Set parameters
After you construct an object, the dot is every parameter of that agent, module, or chip. Later lines win.
craig.prompt = "Review the PR.";
craig.temperature = 0.2;
craig.max_tokens = 2000;
craig.name = "Craig";
check.criteria = ["not empty", "valid JSON"];
Class-level assignments describe the chip itself (id, desc, model, color, …). Any other class-level name is a constant for the lines below.
Practise: Give it a voice · Dial it in
4. Pins and ports
Pins are the public edge of a chip. Everything else is internal.
in ticket : text
out report : text
fail reject : text
A pin's type is any (default), text, json, code, number, boolean, image, audio, or binary. Inside an IC a pin is a module; on a SoC or Board it is a pad. Parents wire a child's pins and never the modules inside it.
Default ports: in1 / out1. Extra inputs land on in2, in3, … fail is the rejected output. You can label a port or keep a hop in a variable: draftIn = writer.port.in1;
5. wire(src, dst) — two parameters
wire is a function with exactly two parameters. Each one is an object, a pin, or a .port.
wire(ticket, craig);
wire ticket -> craig -> brian -> report;
wire(start, [scout, analyst]);
wire([scout, analyst], join);
A chain is sugar for consecutive pairs. A [list] fans out or in. A second wire into an input that already has one lands on in_2.
Practise: Wire it in · Fan out, fan in
6. Wire layers
Wires belong to the layer that owns the objects.
- Inside an IC — agents, modules, and that IC's pins.
- On a SoC — ICs sit here, so wires between ICs go here.
- On a Board — SoCs sit here: user pads in, circuit results out.
An IC holds modules and agents. A SoC holds ICs (a lone agent on a SoC is wrapped as a one-module IC). A Board holds SoCs. The header says which: class X : IC, class X : SoC, class X : Board.
Practise: Two ICs, one SoC · Pads on a Board
7. Packages and files
A chip you save on the desktop is a package: a name the library knows, that any parent can place. A SoC file imports IC packages and never lists the agents inside them. A Board file imports the SoC the same way.
import Studio
class Agency : SoC {
in request : text
out site : text
var studio = Studio();
wire(request, studio);
wire(studio, site);
}
8. Built-in modules
Every built-in is a constructor. Most take no arguments; set their config with the dot. The ones you will use first:
- Merger — join inbound wires.
- Validator / QualityGate — LLM judges. The first line (PASS / FAIL) picks the lane. Wire work to
check.port.payloadif a pass should ship the work, not the review. - Conditional, Retry — also written as
when/retryon an object.
var check = Validator();
check.criteria = ["names an owner", "names a date"];
wire(craig, check);
wire(check, report);
wire(check.port.fail, reject);
Practise: The fail lane · Ship the work, not the review
9. Values and expressions
Everything right of = is evaluated at Save and baked into the chip: strings, numbers, lists, maps, catalog records, and ${} templates.
let WHO = "Craig";
let LIMITS = { fast: 400, deep: 4000 };
craig.prompt = "You are ${WHO}. Under ${LIMITS.fast} words.";
craig.max_tokens = LIMITS.deep;
fn and class-level if also run at Save. They decide what goes into the chip; nothing about them reaches the runtime.
Practise: Values and functions
12. Inheritance and templates
A class can extend another class of the same tier. The base body applies first, then the child's: a later reviewer.prompt wins. A class with parameters is a template — each use on a SoC or Board compiles its own chip with the arguments bound as constants.
class Lane(persona = Persona.TechLead, depth = 1) : IC { ... }
var quick = Lane();
var deep = Lane(Persona.ChiefArchitect, 2);
Practise: One class, many chips · Inherit and override
13. Imports
Three kinds. The two catalogs need none.
import Agency
import Agency@1.0 as AgencyV1
from "lanes/scout.ahl" import ScoutLane
from "path.ahl" import Class reads another source file relative to this one. Cycles, and as renames on a file import, are errors.
Practise: Import a file
14. Operations — run, ask, feed, pos, size
Operations are calls on an object. run("text") is the standing instruction. pos(x, y) and size(w, h) write canvas geometry. Inside a control block, run is the pass instruction for that block.
Practise: Place it on the canvas
15. Control — when, else, retry, loop, each
Control operations mint a Hierarchy chip beside the object and splice it into the wires. One of each per object — combine conditions with and / or instead of a second when.
when(cond)— Conditional on the inbound wire.elsenames the false-leg object.retry(n, until = cond)— Retry Loop on the outbound wire.loop(n, until = cond)— up to n passes, each fed the previous answer.each(list)— one pass per item; answers joined with newlines.
arch.retry(2, until = input.contains("##")) {
arch.run("Use markdown headings.");
}
On a SoC the same forms wrap a child chip, and the parent still never names the agents inside it: lane.when("ready");
Practise: Gate it · Retry until · One pass per item · Gate a whole lane · Refine until done
16. Runtime conditions
when(...) and until = ... take a condition on the value that arrives on the wire. input is that value.
wes.when(input.score >= 8) { wes.run("ship it"); }
craig.when(input.contains("output.ok")) { craig.run("go"); }
Allowed: input.contains / starts / ends / length, comparisons, arithmetic, and / or / not, and JSON fields (input.score, input.result.score). A payload that is not JSON, or has no such key, makes the comparison false.
Practise: Read the payload
18. What runs when
The engine runs a chip as a graph, not as a script. Nothing runs because it was written first: a module runs once everything wired into it has delivered.
- packet — the text on a wire. One module's answer is the next one's payload.
- wave — every module whose inputs are ready runs, then the next set. Two lanes side by side run in the same wave.
- dead lane — a module whose every inbound wire delivered nothing is skipped, so everything after it stays quiet too.
- fan-in — a second wire into one input lands on
in_2. An LLM module reads every inbound port, primary first. - feedback — a Retry Loop's retry wire carries data backwards without making a ring.
What an LLM module is actually sent, in this order: system (persona / .prompt) · instruction (run("...")) · payload (the packet on its primary port). Built-in modules never see an instruction.
A gate splits the wave: the leg that does not take delivers nothing, so its whole branch is dead for that run. That is why a chip with a gate looks half-idle in the log.
19. Test blocks
A test block runs one chip on the Hierarchy engine with canned answers and no LLM calls. Name the chip after for, or put the block right under its class. This is a desktop / aidahl test job — the web lab does not run tests.
test "a clear ticket passes" for Lane {
writer = "BRIEF: add a login page";
check = "PASS";
feed(ticket, "add a login page");
expect(report, contains("login"));
expect(reject, empty());
}
Practise: Write the test
20. Recipes
Five shapes cover most chips. Each one compiles as it stands — on the desktop.
Review + judge
One agent checks another's work; a Validator routes PASS to report and FAIL to reject. Wire the work to judge.port.payload if a pass should ship the work.
Fan-out scan
Two readers on the same text, merged: wire(start, [scout, analyst]); wire([scout, analyst], join);
Retry until shape
architect.retry(2, until = input.contains("##")) { architect.run("Use markdown headings."); }
One pass per item
triager.each(items) { triager.run("Triage this ticket."); }
Score, then instruct
Score first as JSON, then owner.when(input.score >= 8) { owner.run("Ship it."); } else { owner.run("Say what would have to change."); }
23. Errors and Save-refuse
Every error names the file, line and column. Save refuses these — they are not warnings:
wire(src, dst) takes 2 parameters— chain withwire a -> b -> c; fan out with a[list].IC cannot contain ic/Board members must be SoC packages— ICs hold modules only. ICs go on a SoC, SoCs on a Board.unknown wire endpoint— a parent wires the child chip or its pins, never an agent inside it.unknown object—var craig = ...must come beforecraig.promptorwire(craig, …).wire(craig, craig) feeds craig from itself/a ring with no way out— useretryorloop, not a cycle.craig already has a when — one when per object— combine conditions withand/or.duplicate class— two classes with one name in one compile, including a file import that brings a class this file already has.
Warnings (unfed pins, lonely modules, type-lattice mismatches) never stop a Save. The Compile Log still names them.
24. When a chip does nothing
Save said compiled and Run gave you an empty answer. Nine times in ten it is one of these:
- Nothing came out — the out pin is never fed.
- One agent never spoke — nothing is wired into it, or the gate in front of it did not take.
- The gate always takes the same leg — a raw
gate.condition = "..."that reads like code is matched as text, not compiled. Preferwhen(...). - The answer is the review, not the work — wire the work to
check.port.payload. - The second agent got nothing — the second wire landed on
in_2. - Retry never retries —
untilwas already true, or the instruction sits on the object instead of inside the block. - Nothing changed after an edit — the tab was not saved. Ctrl+S is Save + Compile on the desktop.
25. Full walkthrough
The Guide walkthrough on the desktop is a complete IC: named objects, dot parameters, a labelled port, retry until headings, a Validator with a fail pin, and a test block. The web capstone practises that shape.
Practise: Capstone: Night Watch
26. Glossary
| Word | What it is |
|---|---|
| chip | one class: an IC, a SoC or a Board |
| object | something you named with var — an agent, a built-in, or a child chip |
| module | what an object becomes in the compiled document |
| pin | a chip's public edge: in, out, fail |
| port | a named socket on a module (in1 / out1; in_2 is fan-in) |
| packet | the text travelling on a wire |
| lane | a path through a chip; a dead lane was skipped |
| catalog | Agent and Persona — bound without an import |
| package | a saved chip in the library, placed with var name = Package() |
| control chip | the Conditional, Retry, While or For-Each that when / retry / loop / each mints |
| instruction | the run("...") text put in front of the payload |
| spec | a test block: canned answers, a feed, expects |
27. Cheat sheet
class X : IC { } class X : SoC { } class X : Board { }
in a : text out b : text fail c : text
var x = X(Agent.A, Persona.P);
x.prompt = "" x.temperature = 0 x.max_tokens = 0
wire(a, b); wire a -> b -> c; wire(a, [b, c]);
x.when(cond) { x.run(""); } else { y.run(""); }
x.retry(n, until = cond) { } x.loop(n, until = cond) { }
x.each(list) { }
test "name" for X { obj = "answer"; feed(pin, ""); expect(pin, contains("")); }
This is the short card — not the language grammar. Site Save/Compile is a Pro/Team entitlement gate. Lab Check/grade stays desktop teach text.
Practise AidaHL — Pro/Team Save/Compile on aidaide.app
Free / logged-out: teach and practice only — no compile. Upgrade to Pro or Team for the Save/Compile gate. Coming in RC16 — not available to download yet. Windows 1.0.0-rc15 today.
Sign Up Free — DownloadCoding Lab · Pro / Team pricing · AI Hierarchy canvas · Hierarchy Builder docs · Community · Marketplace