Proposal Drafter
The most-hated recurring task at a firm under twenty people, reduced to reviewing a draft.
What it does
Reads two tabs — RateCard and Scope — prices the scope line by line in python, and prints a phase-by-phase table with subtotals and a total. Then it hands that finished table, plus your discovery notes, to the AI, which writes the surrounding SOW: background, objectives, scope of work per phase, out-of-scope, assumptions and dependencies, and an investment section that restates the computed figures.
The message carries the draft first and the pricing table underneath it.
Where the money is computed
In the compose task, in plain python, before the model is called. The AI receives a table it cannot change and is instructed not to produce any figure that is not already in front of it — no arithmetic, no estimates, no invented rates.
This is the whole design. A model that prices your work is a model that will eventually underprice it, in a document you send to a client with your name on it. Delete the narrate task and you still get correct pricing; you just have to write the prose yourself.
A role that appears in Scope with no matching row in RateCard is priced at 0 and called out by name at the bottom of the table. It is not guessed at, and the AI is told to say so plainly rather than smooth over it.
What it does NOT do
This produces a draft. It is not a contract, it is not legal advice, and it is not sendable as-is. It gets you past the blank page, which is the part that takes the week.
It does not know your standard terms, your insurance position, or what you agreed verbally on the call. Out-of-scope in particular deserves your eyes every time — it is where firms lose money, and the model can only infer it from notes you wrote.
Setup
1. Google Sheets
Two tabs in one spreadsheet.
RateCard:
| role | rate |
|---|---|
Scope:
| phase | role | hours | notes |
|---|---|---|---|
Role names are matched case-insensitively between the two. Keep them consistent or you will get a 0-priced line and a callout.
2. Discovery notes
A plain-text or markdown file the InTouch server can read. The first 8,000 characters are used — enough for a long call, short enough that the model stays on the brief.
3. Credential + contact
Replace the placeholders:
- <<GOOGLE_WORKSPACE_CREDENTIAL>> — Google Workspace credential with Sheets read scope
- <<PROPOSAL_SHEET_ID>> — the sheet holding both tabs
- <<DISCOVERY_NOTES_FILE>> — path to the notes
- <<ANTHROPIC_CREDENTIAL>> — used by the narrate task only
- <<PROPOSAL_OWNER_PUBLISHER>> — who receives the draft
4. Schedule
On demand. Run it after a discovery call, not on a timer.
Customization
- House structure. The section list lives in the
narrateprompt. Replace it with your own SOW skeleton — that is the single highest-value edit here. - Local model. Swap
anthropicforollamaand the notes never leave the building. Only the narrative step touches a model, so it is a one-task change. - Drop the AI. Delete
narrateand set the message body to{{compose.output}}for pricing only. - Discounts and fixed fees. Add a column to
Scopeand apply it incompose, so the adjustment is still computed rather than described.
Source
workflow.iml
AI provider
Any supported AI provider works here. This template ships configured for the
anthropic tool; swap that task's tool to anthropic, openai, gemini, mistral,
ollama or openrouter to use the provider you already have, and point its
credential at your own key. The step is a plain summarise/classify call — nothing in
it is vendor specific. See requires.ai in the manifest.