A system for agencies that win work with written proposals. It reads each brief, writes three drafts and has an AI from another company score them on eight criteria, so no model grades its own writing.
A new job landed in the feed while the team was busy with client work. By the time someone sat down to answer it, it was evening, and the proposal started from a blank page.
Whoever wrote it read the brief once, guessed at what the client really needed and wrote one draft. Nobody checked it against a standard, because none was written down: the quality depended on who wrote it and how tired they were. Every bid also cost credits, spent whether or not the client opened it.
When a proposal won, nobody recorded why. The bid credits sat in one spreadsheet tab and the payments in another, and the lesson of last month’s win lived in someone’s memory.
So the hundredth proposal was written the same way as the first.
New jobs all day; someone picks one when they have time
Credits spent, whether or not the client opens it
One draft from a blank page, checked by the writer alone
Often silence; a win or a loss, with no note of why
The system puts one standard between a new job and the client: the same eight criteria and the same phrase check for every draft, and a person who approves every proposal before it is sent.
| Step | Before | With the system |
|---|---|---|
| Find the work | Someone scrolled the feed when they had time and chose what to bid on | Job-alert emails and a browser extension bring each new job in. It is graded for fit against the agency’s profiles, and a good fit is drafted without anyone asking |
| Read the brief | Read once, at the end of the day | Read for the client’s real problem, red flags and how serious the job is, before a word is written |
| Write | One draft from a blank page | Three drafts from one plan, each opening a different way |
| Check | The writer decided it was good enough | An AI from a different company scores every draft on eight criteria, and a rule check bars 64 stock AI phrases. If the best draft misses the bar, its weak part is rewritten and scored again |
| Send | Pasted and sent, often without a second reader | A person reads the best draft with its scores, approves it and sends it. The system sends nothing |
| Learn | Nothing recorded why a proposal won | Each outcome is filed against the proposal and its scores, and a win comes with a written note on why it won |
| Keep the books | Bid credits in one tab, payments in another | Bid credits, refunds and payments post by themselves, and every change keeps an audit trail |
Brief: Tallis & Rowe Interiors want their quotes out faster
Draft A passed every check: 4.45 of 5
Two days per quote is slow, and a quote sent with last month’s prices costs you margin. Both come from the same place. … If you send me one recent quote, I will show you on a short call where each of its prices would come from.
I’d start with your last ten proposals: the ones that won and the ones that did not.
Together they show what a winning proposal of yours looks like, and that becomes the written standard every draft is scored against. The first version drafts into the tools your team already uses, and your team approves and sends every proposal.
Discuss a system like thisKorCRM is one web app and a set of workers over one Postgres database. Jobs come in from email and a browser extension, workers on a queue grade and draft them, and the web app holds the review queue, the clients and the books.
The web app is Next.js 16, with six views named for the work: Today, Hunt, Craft, Deliver, Money and Learn. The workers run on BullMQ and Redis, and every model call goes through one LiteLLM proxy, so each stage’s model is a setting in its pipeline configuration.
Every change to a record writes an append-only audit row with who made it, when, and the values before and after.
Job-alert emails and the browser extension, merged into one job record
Gmail API, WXT, BullMQGraded against the agency’s profiles; 0.60 or more starts a draft
gradeWorker, job-data-gateRead, plan, three drafts, a judge from another company, the weak part rewritten
5 stages, LiteLLMThe best draft with its scores, approved or rejected, then sent by a person
review queueOutcomes filed per proposal, 11 money rules, an audit row on every change
Postgres, prisma.$transactionOne database and one deploy, split into 22 packages. The nine domain packages never import each other: reads cross a border through ports, and writes go through named flows such as submitProposal.
When a proposal goes out, its bid credits are debited; when credits are refunded, they come back; when a client pays, the payment becomes a transaction and updates the work log. Eleven automation rules like these fire on the changes they watch.
Follow the fictional brief from sheet 4 through the drafting stages, from the job alert to the person who sends the proposal. The left edge of the drawing shows who does each step.
Job-alert emails come in through the Gmail API, and the browser extension reads the job feed, job pages and sent proposals with three extractors. Workers on a queue merge both streams into one job record. A job with no title, or a description under 40 characters, is flagged for a person and never graded. The rest are graded for fit against the agency’s profiles, and a grade at the threshold, 0.60 by default, starts the drafting by itself.
The brief is read for the client’s real problem, red flags and a job-quality score. A planning stage on Claude then chooses the opening, the framing, the proof point and the structure. Planning is its own stage, so all three drafts argue from the same plan.
Claude writes three drafts in parallel from the same plan, each phrased differently at temperature 0.8. The budget tier writes one draft to save cost.
A GPT judge scores every draft from 1 to 5 on eight weighted criteria, and code runs five rule checks at no cost: 64 stock phrases, sentence-length variety, “you” against “I”, length and the opening word. The writer and the judge come from different AI companies, so no draft is scored by the model that wrote it. The best weighted score is kept.
Draft A leads at 4.40, but its ending scores 3 for a clear next step.
A draft passes when all eight criteria reach 4, no stock phrase appears and the weighted score reaches 3.5. A draft that misses is rewritten on its weak criteria and scored again from scratch, up to two times. Here one rewrite lifts the ending to 4 and the draft to 4.45.
The draft lands in the review queue with its scores and checks, marked if it still missed after two rewrites. A person approves or rejects it and sends it on the marketplace. Each outcome, from opened to hired or lost, is filed against the proposal, and each evaluation keeps the weights it was scored with, so old scores never change. A win triggers a written note on why it won. Nothing is sent until a person sends it.
Claude plans and writes; a GPT model judges. Both sit behind one LiteLLM proxy, so moving a stage to another model is a configuration change.
Anything a rule can decide is decided in code: the five checks on every draft, and the data gate that keeps a job with no description away from the grading model.
Each row is a finding from building and running the system, settled where it started.
Most became standing rules, checked by the linter or by the code on every run. Each row traces to a commit, a decision record or the changelog.
Every draft the system writes is scored against one written standard, and a person approves every proposal before it is sent.
A version for your agency starts from the same method, with three drafts scored by a judge from another AI company and a person on every send, and adds what your team needs.
If your proposals still start from a blank page, the fix starts with your last ten, the ones that won and the ones that did not. Bring them.