Skip to content

Learn

Analyse your first file

Run a whole job on the example, offline, read the summary, open the report and trace a number back to its rows.

Tutorial 1 of 5. About ten minutes. No model, no API key, no internet after installing.

You will run the engine on the example files, read what it found, and check one number all the way down to the spreadsheet rows.

You need Bun (the package manager) and Node 22. From a clone of the repository:

Terminal
bun install
bun run aa doctor

aa doctor lists what is configured. It will say no model is reachable, which is fine for this tutorial.

Terminal
AA_DEMO_MODEL=scripted bun run aa analyze examples/coffee-roaster --yes --embedder hash --today 2026-07-01 --currency USD

What the parts mean:

  • AA_DEMO_MODEL=scripted replaces the language model with the scripted planner, a replay of a model’s decisions for this example. Leave it out once you have a model configured.
  • examples/coffee-roaster is a folder; every file in it goes in.
  • --yes keeps the drafted metric definitions as assumptions instead of asking you (the next tutorial does the asking).
  • --embedder hash uses the offline embedder, so nothing is downloaded.
  • --today fixes the date, so “future dates” and check dates come out the same as here. --currency says what the unmarked money columns are in.

This is what it printed:

Recorded output, offline run
$ AA_DEMO_MODEL=scripted bun run aa analyze examples/coffee-roaster --yes --embedder hash --today 2026-07-01 --currency USD
Scripted demo model (no LLM): a deterministic replay for examples/coffee-roaster.
job <job-id>
▸ INGEST
✓ INGEST (… ms)
▸ PROFILE
✓ PROFILE (… ms)
▸ METRICS_DRAFT
✓ METRICS_DRAFT (… ms)
▸ MEASURE
✓ MEASURE (… ms)
▸ DETECT
✓ DETECT (… ms)
▸ DECOMPOSE
✓ DECOMPOSE (… ms)
▸ INDEX_DOCS
  … indexing documents (an in-process embedding model, if used, is downloaded on its first use)
✓ INDEX_DOCS (… ms)
▸ EXPLAIN
  … finding 1 of 5 explained
  … finding 2 of 5 explained
  … finding 3 of 5 explained
  … finding 4 of 5 explained
  … finding 5 of 5 explained
✓ EXPLAIN (… ms)
▸ DECIDE
✓ DECIDE (… ms)
▸ VERIFY
✓ VERIFY (… ms)
▸ RENDER
✓ RENDER (… ms)

Revenue fell after March, driven by wholesale (a change of −7,900).

Findings:
• Revenue fell after March, driven by wholesale
  Revenue went from 44,100 in 2026-03 to 36,200 in 2026-04 (a change of −7,900, −17.9%). It stood at 37,000 in 2026-06.
• Refund rate rose after the packaging supplier switch
  Refund rate went from 1.2% in 2026-03 to 1.3% in 2026-04 (a change of 0.1 pp, 8.3%). It stood at 3.4% in 2026-06.
• A change in revenue
  Revenue for “Green Leaf Bakery” went from 2,745.86 in 2026-05 to 1,966.87 in 2026-06 (a change of −778.99, −28.4%).

Recommendations:
• Offer wholesale accounts a volume-tier discount to win back paused standing orders
  Expected impact: 3,995 to 7,191 next quarter
• Return to the previous packaging supplier, or fix the new valve bags
  Expected impact: 407 to 732.60 next two months

Note: some metric definitions were assumed, not confirmed. Check them in the report's Metrics section.

report: agentic-analytics/report.json
html:   agentic-analytics/report.html

Replaced in the recording because they change on every run: stage durations, the job id (a timestamp), the report folder (the current folder).

The ▸/✓ lines are the stages, in order: the same ones the Learn overview walks through. Then the summary: the headline, the findings, the recommendations with their impact ranges, and a reminder that the metrics were assumed.

The job wrote agentic-analytics/report.json and agentic-analytics/report.html in the current folder. Open the HTML file in a browser (or add --open to the command). Every number in it is followed by a fact ID; click one to see how it was computed.

Take the headline percentage from the summary. Ask where it came from, using the job ID the run printed (bun run aa jobs ls lists them):

Recorded output, offline run
$ bun run aa explain <job-id> N30
N30 = −17.9%   (I5 trend_break.v1 revenue 2026-04:change_pct)
function: pct_change
  N11 = 36,200   (revenue_2026-04)
  N12 = 44,100   (revenue_2026-03)

It is a function, pct_change, of two other facts. Open one of them:

Recorded output, offline run
$ bun run aa explain <job-id> N11
N11 = 36,200   (revenue_2026-04)
definition: Revenue = sum of amount where status is empty or status is not refunded, per month, in USD (assumed)
sql:
  WITH m1 AS (SELECT strftime("date", '%Y-%m') AS period, sum("amount") AS value FROM "t_t1" WHERE NOT _is_total AND "date" IS NOT NULL AND (("status" IS NULL) OR ("status" NOT IN ($1))) AND strftime("date", '%Y-%m') BETWEEN $2 AND $3 GROUP BY ALL)
  SELECT period, value FROM m1 ORDER BY period
params: {"$1":"refunded","$2":"2026-04","$3":"2026-04","input_rows":1020}
input rows from T1 (20 shown):
  {"_row":3095,"_is_total":false,"_period":"2026-04","date":"2026-04-01T00:00:00.000Z","order_id":"CR-03094","customer":"Shop counter","channel":"retail","product":"Filter blend 250g","qty":2,"amount":32.9,"status":"paid"}
  {"_row":3096,"_is_total":false,"_period":"2026-04","date":"2026-04-01T00:00:00.000Z","order_id":"CR-03095","customer":"Online store","channel":"retail","product":"Filter blend 250g","qty":1,"amount":20.98,"status":"paid"}
  {"_row":3097,"_is_total":false,"_period":"2026-04","date":"2026-04-01T00:00:00.000Z","order_id":"CR-03096","customer":"Online store","channel":"retail","product":"Filter blend 250g","qty":1,"amount":35.88,"status":"paid"}
  {"_row":3098,"_is_total":false,"_period":"2026-04","date":"2026-04-01T00:00:00.000Z","order_id":"CR-03097","customer":"Online store","channel":"retail","product":"Drip bags x10","qty":1,"amount":29.63,"status":"paid"}
  {"_row":3099,"_is_total":false,"_period":"2026-04","date":"2026-04-01T00:00:00.000Z","order_id":"CR-03098","customer":"Online store","channel":"retail","product":"Espresso blend 250g","qty":2,"amount":25.97,"status":"paid"}
… (5 more lines)

That is the whole chain: a percentage, from two monthly totals, from one SQL query with its parameters, from these rows of the Orders sheet. Nothing in between was written by a model.

Recorded output, offline run
$ AA_DEMO_MODEL=scripted bun run aa ask <job-id> "why did revenue fall in April?"
Scripted demo model (no LLM): a deterministic replay for examples/coffee-roaster.
• Revenue went from 44,100 in 2026-03 to 36,200 in 2026-04 (a change of −7,900, −17.9%). It stood at 37,000 in 2026-06.
(1 statement(s) failed verification and were left out)

The answer is made of claims that went through the same verifier as the report, and a statement that failed verification was left out (it says so).

  • One command runs the whole pipeline; the stages print as they go.
  • Every number has an ID, and aa explain opens its computation.
  • The scripted planner makes this reproducible; a real model changes the wording, not the numbers.

Next: Confirm your metrics, so the numbers mean what you mean.