Drafting a funding proposal without inventing a single figure
A funding call arrives as a PDF, sometimes with a Word concept note and an Excel budget. The engine fills the funder's own files, marks what it does not know, and hands the result to a reviewer. Nothing is invented.
Flow
- Ingest. A link, pasted text or files (PDF call, DOCX and XLSX templates, annexes). Files go to blob storage under the opportunity.
- Extract. Claude reads the call (PDF natively) into a structured record: funder, reference, deadlines, locations, sectors, expected results, weighted criteria, required documents, data-protection clauses. The output is validated against a Zod schema before it is stored.
- Analyse the templates. Each DOCX or XLSX is read at OOXML and cell level into a skeleton of locators. The model decides which locators are slots to fill, with the funder's instruction and an expected length. A validated slot map is cached by fingerprint, so a funder reusing its form is recognised next time.
- Generate, slot by slot. From the call, the organisation's curated knowledge base and the reviewer's guidance. Every slot comes back with its sources, a confidence score and a to-verify list. A fact missing from the knowledge base becomes a
[TO COMPLETE]marker. - Render in place. Content is written back into the original files: styles kept, budget formulas kept and shifted when rows are inserted. Free-form notes are produced as Markdown, then Word.
- Review. Reviewers are notified in-app and by e-mail; they edit sections, regenerate some with guidance, assign, approve and mark the proposal submitted.
- Watch. A daily worker polls the configured sources (UN Partner Portal API, HTML pages, RSS feeds) and creates new opportunities as they appear.
Human gates
Nothing leaves the organisation without a reviewer approving it. The engine drafts; people submit.
Regeneration is scoped: a reviewer regenerates one slot with a written guidance, not the whole document.
Permissions follow the platform's RBAC: tenders managers, headquarters administrators and team leaders run the engine; finance managers approve.
What never reaches the LLM
Facts that are not in the knowledge base. The prompt forbids stating anything about the organisation that does not appear in the provided records; the schema forces a to-verify list on every slot.
The funder's formatting. The model returns content for a locator; the rendering layer owns the document.
Decisions and why
Why structured outputs rather than a chat. The deliverable is the funder's file. A locator and a schema make an interface contract; free text would need a human to copy it over and would drift.
Why OOXML cell by cell. Funders score the form they sent. Rewriting it as a summary would lose the budget formulas, the numbering and the instructions that reviewers rely on.
Why a knowledge base and markers. The most expensive error in a proposal is a confident wrong number. Missing facts are surfaced, never guessed.
Why cost per opportunity. Each generation adds up input, output and cached tokens into a tally stored on the opportunity, so the price of a draft is known before anyone asks.
Why prompt caching. The call and the knowledge records are the same across slots; caching them keeps a multi-slot draft affordable.
Numbers
3 source adapters (UN Partner Portal, HTML, RSS) watched daily by a PM2 worker.
5 data models, one engine directory with extraction, template analysis, generation, rendering, sources and notifications, and 5 command-line scripts for ingestion, generation, watching and knowledge seeding.
Part of Aria: 18 modules, 13 RBAC roles, 63 data models, 21 ADRs, 6 releases, deployed on Azure behind Front Door and a WAF.
Stack
See also
AI Product Factory: how an idea becomes a reviewed pull request
Pilume: an AI that explains a medication schedule but never decides it