Our architecture has always drawn a line: the model composes, the data states the facts. Places, climate, visa status, money — all of it arrives from records before a word is written, and the model's job is to arrange and explain.
Follow that line far enough and an awkward question appears. If everything factual comes from the collection, and the model only arranges it — how much of the arrangement could also be done in code?
Rather more than we expected.
Every section, built locally
There is now a second composer that produces a full plan with no model involved at all. Every section is assembled from what we already hold: the verified place cache, per-city packs of climate and currency and holidays, curated city guides and city facts, food guides, country facts, advisories, and the visa table.
The entities were never the model's to invent, and it turns out the prose around them need not be either.
It is not as good. Model-composed prose is more fluent, better paced, and better at explaining why an ordering makes sense — that is a real skill and we are not pretending otherwise. But the local version is not a stub either. It is a complete, readable, correctly grounded plan, and for some sections the difference is genuinely hard to spot, because those sections were always mostly structure.
The rule that keeps it honest
One rule governs every local builder: return nothing rather than fill a section the collection cannot ground.
This is the same principle as the rest of the product, applied to ourselves. A code-written section is no more entitled to invent a restaurant than a model-written one, and it would be easy to let a template quietly emit a plausible-sounding sentence about a city we hold almost nothing on. A builder that cannot ground its section declines to write it, and the plan carries the gap.
What it is for
Its first job is repair. Plans whose generation died — a provider outage mid-pass, a run of quota errors, an infrastructure failure — used to be stuck as permanently unfinished. They can now be completed offline from the collection, without spending another model call, and without asking the traveller to regenerate a plan they already have.
Its second job is insurance. Every LLM provider we use has rate limits, outages and quota ceilings, and a product whose core function stops working when a third party has a bad afternoon is not really a product. There is now a floor: a plan that can always be built, from data we hold, on hardware we control.
There is a quieter benefit too. Writing the local version forced us to state, in code, exactly what each section is made of — which turned out to be the most rigorous audit of our own grounding claims we have done. You cannot write a builder for a section you do not fully understand the inputs to.
Put it to the test
Every claim in this post is something you can check on a real plan. One sentence is enough to start one.