01
All projects
2025Internal AutomationAI Agents
// project.consolidator-pipeline

Consolidator Pipeline

Analyst & Builder

An internal pipeline that replaced manual flight-fare research with one-click batch runs — gathering, processing and analysing thousands of fares automatically.

Request a walkthrough
automations.internal/consolidator/run
automations / consolidator batch
job 7f3a91RUNNING
Consolidatorpartner_03 ▾
RequestFlight Search ▾
Routes filetop_200_routes.json ▾
Departure date(s)2026-07-02, 2026-07-09
Benchmark against own fares
Running…
$ automations.consolidator.run · live log
Starting consolidator batch: partner_03
Merged 400 route entries (200 routes × 2 dates)
Running batch: 400 concurrent API requests
ARN→BKK 2026-07-02 · 200 OK · 412 ms
CPH→JFK 2026-07-02 · 200 OK · 388 ms
OSL→DXB 2026-07-09 · 200 OK · 521 ms
HEL→NRT 2026-07-09 · 200 OK · 633 ms
--- Batch complete ---
Parsing responses…
Total offers: 2,847
Benchmark merged · prices → EUR
Uploaded: 2026-07-02_partner_03_report.html
312 / 400 requests

fig. 01 — a batch run: one form, live-streamed logs, a finished report. UI recreated; internal data anonymised.

02

The Manual Process

A consolidator is a potential partner company — a wholesaler that sells airline fares through its own API. Before we work with one, someone has to answer a deceptively simple question: are their prices actually competitive? Until recently, answering it meant people searching flights by hand on websites — route by route, date by date — and copying prices into spreadsheets. A single evaluation tied up people for days, the data was inconsistent, and by the time it was assembled the fares had already moved. I built the automation that replaced that process end to end: data gathering, data processing and data analysis, with a human only at the start and at the end.

One Batch, End to End

To the analyst, the whole thing is a form: pick the partner, pick a routes file, type the departure dates, press run. From there the pipeline takes over. It merges the route list with the partner's request defaults — one entry per route per date — fires the API requests as a concurrent batch, and streams every log line live to the browser, so progress is something you watch rather than wait for.

[01]
Routes × dates
merged into one request set
[02]
API batch
concurrent requests, live logs
[03]
Raw responses
one JSON file per route
[04]
Parse & normalise
mapping config → clean rows
[05]
HTML report
tables · charts · benchmark
fig. 02 — one run: from a route list to a shareable analysis

Every raw response is parsed into normalised rows — price, taxes, carrier, segments, baggage, response time — using that partner's mapping config. Prices are converted to a single currency and matched against our own production fares for the same routes, so every partner offer lands next to the number it has to beat. The output is a single self-contained HTML file with sortable tables and charts: open it in any browser, no installs, no exports. Several partners can also run against the same routes in one go, and the pipeline generates a combined comparison report at the end.

Every API Speaks Its Own Dialect

The expensive part of this system was never sending the requests — it was onboarding. Every partner's API returns a differently shaped JSON document. Some nest flight segments inside each offer; others keep offers and flights in separate lists joined by reference IDs. Prices are sometimes bare fares and sometimes tax-inclusive totals. Timestamps arrive in a different format every time. So I made the parser config-driven: one generic parser, plus a per-partner response mapping that tells it where everything lives. That reduced onboarding to producing one config file — and then I built an AI agent pipeline that produces it.

The Response-Mapping Agent

Onboarding a new partner today means uploading two files — their API request collection and a single sample response — and letting a pipeline of four small LLM agents do the rest. Each agent has a narrow job and at most two tools; the heavy JSON never enters a prompt.

request collectionsample JSON response
[1]Profiler
compresses the sample into a compact schema sketch
[2]Classifier
reference or inline shape? locates the offer & flight lists
mapping loop · max 6 iterations
[3]Mapper
drafts the mapping, peeking at real paths & values with tools
[4]Validator
runs the real parser on the sample with the draft mapping
↩ on failure: a concrete issue list goes back to the Mapper
rows parse cleanly → validated response_mapping config saved
fig. 03 — the agent pipeline that writes a new partner's parser config

The design principle is: never trust the model, verify by execution. The Mapper's draft is never accepted on its own merits — the Validator runs the actual production parser against the sample response and reads the result. If zero rows come back, or prices and timestamps are malformed, it writes a specific list of what failed and the loop sends the Mapper back to fix exactly those issues. Only when real rows parse cleanly does the loop exit. The prompts also encode the domain traps I kept hitting by hand: bare fare versus tax-inclusive total, path syntax the parser actually supports, timestamp format strings confirmed against real values rather than guessed.

How It Worked Out

Nobody searches flights by hand for these evaluations anymore. A multi-date batch across hundreds of routes completes in minutes, benchmark included, and produces a report anyone can open and explore. Evaluations became repeatable — same routes, same dates, re-run next week and compare. And because onboarding collapsed from a developer-day of JSON archaeology to a few minutes of agent compute, we can evaluate far more potential partners than before — the bottleneck is now the decision, not the data.

// reach.out

Working on something similar?

Tell me where the time goes in your process, and I'll tell you what an agent could take off your plate.

Let's talk
[MODE: READING ]// project.consolidator-pipeline
agents: online0 %--:--