A small IT firm can lose two days on a bid before it finds the one line that rules it out: a minimum yearly turnover, a staff count per role, a certificate. That line sits in the tender's selection criteria, in German, Dutch or French, and when the notice sends you to the procurement documents it can be fifty pages in.
I built Pagefifty for the Nebius x NVIDIA Global AI Hackathon to read that line first.
What it does
A capture command asks TED, the EU's tender database, for open IT notices that buyers in the Netherlands, Belgium and Germany published in the last 14 days. For every lot that publishes its selection criteria, NVIDIA's Nemotron 3 Super on Nebius Token Factory reads the clauses and returns typed requirements as JSON, each with a verbatim quote. Code compares those requirements with the firm's profile, in the visitor's browser, and every lot gets "Go", "Not met alone" or "Ask first", with the deciding clause quoted under it and a link to the notice.
Take notice 713597-2026, a German federal framework contract. It asks for EUR 1,400,000 a year in turnover in the field. The demo firm made EUR 1,090,000, 1,210,000 and 1,240,000, so the lot reads "Not met alone", and the page explains that Article 63 of the EU procurement directive lets another firm lend that turnover or bid jointly. For a small firm, "not on your own" is a different answer from "no".
The idea that shaped it
The model never gets the last word. Code has to find each quote in the clause it came from, word for word once spacing, line breaks, hyphens and curly quote marks are evened out. A quote it can't find, or one shorter than 12 characters, is refused, and the criterion shows as "Not read". Every amount, count and year is parsed by code from a verified quote, never from the model's own fields.
On 22 October the model gave 1,865 quotes across 288 lots, and code refused 76 of them. Notice 699142-2026 shows what that costs: the model turned a clause's double quotes into single ones, so none of its three quotes matched, and a staff count that was actually right reads "Not read". I'd still rather show that than a figure nobody can trace back to the tender.
What I learned
- Thinking is on by default, and it costs. One German lot used 4,101 reasoning tokens, 22.4 seconds and USD 0.00532. With
enable_thinking: falsethe same lot took 6.1 seconds and USD 0.00181 and still came back as valid JSON. A Dutch lot with thinking on spent its whole 8,000-token budget thinking and returned nothing. - The server didn't enforce my JSON schema. One French reply broke JSON with a raw tab copied straight out of the tender. Every reply now goes through Zod, a raw tab becomes a space, and a failed reply gets one repair retry with the validation errors in the prompt.
- The full read cost USD 0.275838 for 225 calls, 293,177 tokens in and 208,761 out. That's under a tenth of a US cent per lot.
- Most of the time the rule really is on page fifty. 123 of the 323 notices published no selection criteria in the notice at all, so this version answers "Ask first" for them, and reading the document packs comes next.
- A web search is a lead, not evidence. One Tavily search per notice on the buyer's name kept 658 of 1,000 results after a tender-word filter. They show apart, unchecked, and never change an answer. For 713597-2026 my query brought back five pages about Florida's time zone.
What it isn't yet
There's one live model run so far, so I can't yet say how much the reading varies between runs. The quote check proves the words are the tender's own, not that the model read them right. And the demo firm is invented.
Links
- Try it, no account: https://pagefifty.atfyigtaran.workers.dev
- Demo video: https://youtu.be/NZ8mjAI7mMo
- Code, MIT: https://github.com/voyagi/pagefifty
- Devpost: https://devpost.com/software/pagefifty
Top comments (0)