Your First AINL Workflow: Hello World to Real Output
This guide takes you from a clean install to a working, validated, compiled AINL program — step by step. No shortcuts, no skipped errors.
What you'll build:
- A minimal hello-world program (2 lines)
- A branching status workflow (real control flow)
- A cron-triggered monitor (repeating, stateful)
Prerequisites
You need AINL installed. If you haven't done that yet, follow the install guide first.
Confirm it's working:
ainl-validate --version
And confirm the examples directory exists:
ls examples/
You should see files like hello.ainl, status_branching.ainl, monitor_escalation.ainl.
Part 1: Hello World
The canonical hello-world workflow in AINL is examples/hello.ainl. Here's what's in it:
L1:
R core.ADD 2 3 ->x
J x
Let's break that down:
L1:— a label (block entry point). All executable ops belong to a label.R core.ADD 2 3 ->x— a request: call thecoreadapter'sADDverb with arguments2and3, and store the result in variablex.J x— return the value ofxas JSON output.
Validate it
ainl-validate examples/hello.ainl --strict
You should see no errors. --strict enables the full set of invariant checks (no undeclared references, no unreachable nodes, canonical IR emission).
Inspect the compiled graph IR
ainl-validate examples/hello.ainl --strict --emit ir
This prints the canonical graph IR — the internal representation the runtime actually executes. You'll see the program reduced to a set of nodes and edges. That graph is what gets executed, not the source text.
Run it
ainl run examples/hello.ainl --json
Expected output:
{"x": 5}
That's 2 + 3 = 5. The program compiled to a graph, the runtime walked the graph, the core.ADD adapter returned 5, and J x emitted it as JSON.
Part 2: Branching (If / Set / J)
Real workflows branch. Here's examples/status_branching.ainl:
L1:
Set status "ok"
If status=ok ->L2 ->L3
L2:
Set out "ok"
J out
L3:
Set out "alerted"
J out
What this does:
Set status "ok"— assign the string"ok"to variablestatusIf status=ok ->L2 ->L3— branch: ifstatusequalsok, jump toL2; otherwise jump toL3- Labels
L2andL3each set an output variable and return it withJ
Strict literal policy: In strict mode, bare identifiers in read positions are treated as variable references. Always quote string literals explicitly —
"ok"notok.
Validate and run
ainl-validate examples/status_branching.ainl --strict
ainl run examples/status_branching.ainl --json
Expected output: {"out": "ok"} — because status was set to "ok" and the branch took the ->L2 path.
Try changing Set status "ok" to Set status "alerted" and re-run. The output will be {"out": "alerted"}.
Part 3: A Cron-triggered Monitor
Here's examples/monitor_escalation.ainl:
S core cron
Cr L_tick "*/5 * * * *"
L_tick:
R core.MAX 7 3 ->metric
If metric ->L_escalate ->L_noop
L_escalate:
Set out "escalate"
J out
L_noop:
Set out "noop"
J out
What's new here:
S core cron— service declaration: this is a scheduled (cron) workflow, not a web APICr L_tick "*/5 * * * *"— cron definition: run labelL_tickevery 5 minutesR core.MAX 7 3 ->metric— compute the max of7and3, store inmetricIf metric ->L_escalate ->L_noop— branch based on whethermetricis truthy
Validate it:
ainl-validate examples/monitor_escalation.ainl --strict --emit ir
This is the shape of a real recurring AI monitor — check a value, branch on a condition, return a status.
What you've learned
| Concept | How it looks in AINL |
|---|---|
| Labels (entry points) | L1:, L_tick: |
| Adapter calls | R core.ADD 2 3 ->x |
| Return output | J x |
| Set a variable | Set status "ok" |
| Branch on condition | If condition ->L2 ->L3 |
| Cron schedule | S core cron + Cr L1 "*/5 * * * *" |
