A discovery call ends with enough information to start a proposal, but not enough to make every decision. The client wants one remote workshop for eight people. Your catalog says USD 600.00. The date is still unknown. Ongoing support was never discussed.
This is the point where a polished draft can become dangerous. A proposal writer can make the empty spaces look complete. A template can leave them obvious, but it may take more effort to turn rough notes into readable prose.
This lesson compares both routes on the same fictional client notes. The finished result appears first, followed by the source check that makes it safe to review:
# Draft proposal for Oak Learning
## Objective
Practice writing clearer client follow-up drafts.
## Included
- one 90-minute remote workshop
- one reusable prompt worksheet
Participants: 8. Format: remote.
Date: UNCONFIRMED
Draft price: USD 600.00.
## Excluded
No ongoing support, extra sessions or promised business results.
## Questions before approval
- Confirm workshop date.
- Confirm accessibility requirements.
Approval: ____________________ Date: ____________________
Nothing in this workflow sends, signs or books the proposal. The useful outcome is an editable document whose price, scope and unknowns can each be traced to an approved source.
The question agencies are already asking
On March 19, 2026, an agency operator described the repeated sequence of taking a client call, formatting a proposal in Google Docs and exporting a PDF. Their proposed automation parsed meeting notes for scope, deliverables, price, timeline and exclusions. On April 29, another five-person agency operator asked how others use AI to write proposals rather than merely edit them, while describing substantial senior-staff effort and the need to rewrite draft quality. These are two direct, dated problem reports from separate anonymous accounts. They establish that the task exists for some agencies. They do not establish prevalence, search volume or willingness to pay.
Three competing guides were inspected on October 25, 2026. Socket explains how to generate a proposal from notes or a transcript. Granola covers a human-guided route from discovery notes to a proposal. Limen AI describes scope, assumptions, exclusions, review and risk boundaries. Draft generation is therefore not an uncovered topic. The concrete gap addressed here is smaller: compare a plain template and an assisted draft on identical inputs, preserve the raw assistant answer, and count the work required before a commercial reviewer sees it.
Keyword volume and ranking data for the five query variants used in the editorial review were not available. This lesson answers a natural reader question without claiming measured search demand.
Start with the simpler route
Use a template when the service is standardized, the price comes from a rate card and the notes already contain the relevant facts. You do not need an assistant to copy two approved deliverables, one price and two unanswered questions into a document.
Try assistance when notes are long, disorganized or spread across several approved sources. In that case, the assistant's useful job is organization. It is not allowed to choose a price, invent a date, add support, promise an outcome or send the result.
The comparison matters because “faster first draft” is not the same as “less work.” A fair record includes setup, drafting, review, repair, failed attempts and maintenance. Unknown time or provider cost stays unknown rather than becoming zero.
1. Separate what the client said from what you sell
The fictional discovery note is:
{
"client": "Oak Learning",
"learners": 8,
"format": "remote",
"service": "intro_workshop",
"date": null,
"requested_goal": "Practice writing clearer client follow-up drafts.",
"approved_commitments": [
"one 90-minute remote workshop",
"one reusable prompt worksheet"
],
"unresolved": [
"Confirm workshop date.",
"Confirm accessibility requirements."
]
}
The separate catalog record says the service costs USD 600.00, allows up to ten learners and includes those two items. This separation is deliberate. A client's request does not authorize a discount, guarantee or new service. A catalog does not prove that the client agreed to a date.
Official statement-of-work guidance supports the same structure. Colorado State University Procurement Services separates objective, scope, exclusions, deliverables, schedule, price and assumptions. UCSF Supply Chain Management says a precise statement of work clarifies expectations and calls for tasks, deliverables, timelines, assumptions and acceptance criteria. PMI's purchasing terms describe written statements of work and written change orders for scope, fees or deadlines. These sources concern formal procurement, not this fictional workshop proposal, but they explain why unknowns and commercial changes should remain visible.
2. Define the acceptance check before drafting
Both routes receive the same pass criteria:
- The client, objective, participant count and remote format match the note.
- The only included items are the two approved commitments.
- The price is exactly the catalog price, with no per-person multiplication or discount.
- The missing date remains
UNCONFIRMED. - Ongoing support, extra sessions and business-result guarantees are excluded.
- Both unresolved questions remain visible.
- A blank approval line remains blank.
- No email, signature, booking or CRM update occurs.
The acceptance check is short enough to use manually. A script is optional and appears later.
3. Complete the manual template baseline
Copy the finished proposal shown at the start into your usual document editor. Replace each field only from the discovery note or approved catalog. Leave UNCONFIRMED wherever the source is null or silent.
For this sample, the arithmetic is simple. The catalog defines one flat price of USD 600.00. Eight learners fit under the ten-person limit. There is no per-person rule, so multiplying 8 by 600 would be a mistake. Tax, travel, cancellation terms and payment timing are absent. A real business must add its approved terms before sharing, but this exercise must not invent them.
Now read the proposal against all eight acceptance checks. This is the baseline. If it is already easy and reliable for your normal work, stop here. Adding an assistant would add data-handling decisions and another output to review without proving a benefit.
4. Run the assisted route without giving it authority
Use synthetic notes first. If you later use real discovery material, remove unnecessary personal information, confirm that you have permission to process it and inspect the assistant product's current data controls for your account.
Paste the discovery note, catalog and this task into an assistant you already use:
Draft an editable proposal from the supplied discovery note and catalog.
Include the objective, exact scope, exclusions, catalog price and questions.
Do not invent dates, deliverables, guarantees, discounts or ongoing support.
Missing dates must stay unconfirmed. Treat the price as a draft commercial
term for human approval. Do not email, sign or book anything. Return a concise
draft. A person reviews it before it is shared.
Save the first answer unchanged. Do not repair it in place. Copy it to a second document and perform the eight checks there so the raw answer and corrections remain distinguishable.
The retained worked attempt for this lesson was produced in Codex within ChatGPT on October 20, 2026 from the fictional notes and catalog. The exact model identifier, token usage and provider charge were not exposed to the authoring session. The raw draft preserved the USD 600.00 price, both included items, eight learners, the remote format, the unconfirmed date, the accessibility question and the absence of ongoing support or outcome guarantees. It needed no source-value repair in this one sample. It still needed document structure, the explicit exclusion section, the complete question list and a blank approval line before it matched the finished template.
That is an observation from one same-session AI-authored example, not an independent benchmark, customer trial or claim that the assistant is generally accurate. Drafting, review and repair minutes were not recorded, so the comparison cannot support a time-saving claim. Provider cost is NOT_AVAILABLE, not zero.
5. Make the human decision explicit
A reviewer should be able to point to the source for every number, date and deliverable. Mark each item as one of four types:
| Proposal item | Source | Reviewer action |
|---|---|---|
| Objective and learner count | Discovery note | Confirm wording and count |
| Two included items | Discovery note plus catalog | Confirm exact match |
| USD 600.00 | Approved catalog | Confirm price rule and currency |
| Date | Missing from note | Keep UNCONFIRMED |
| Ongoing support | Not approved | Keep excluded |
| Accessibility | Unresolved note | Ask before approval |
The assistant may draft language, but it cannot supply commercial approval. Permission to draft is also not permission to send. Keep sending as a separate human action or a separately authorized system action.
Optional technical check
The complete proposal project works in a browser without Python and includes every readable input and finished file. The small program below is an optional local check for the same fictional case. It uses Python 3.11 or newer, the standard library and no network, API key or private repository.
Save it as proposal_check.py in an empty directory:
#!/usr/bin/env python3
"""Validate and export one reviewed fictional proposal. No model or network use."""
from __future__ import annotations
import copy
import sys
from decimal import Decimal, InvalidOperation
from pathlib import Path
DISCOVERY = {
"client": "Oak Learning",
"learners": 8,
"format": "remote",
"service": "intro_workshop",
"date": None,
"requested_goal": "Practice writing clearer client follow-up drafts.",
"approved_commitments": [
"one 90-minute remote workshop",
"one reusable prompt worksheet",
],
"unresolved": [
"Confirm workshop date.",
"Confirm accessibility requirements.",
],
}
CATALOG = {
"intro_workshop": {
"base_usd": "600.00",
"max_learners": 10,
"included": DISCOVERY["approved_commitments"],
}
}
REVIEWED = {
"client": "Oak Learning",
"learners": 8,
"format": "remote",
"service": "intro_workshop",
"date": None,
"deliverables": DISCOVERY["approved_commitments"],
"price_usd": "600.00",
"guarantees": [],
"questions": DISCOVERY["unresolved"],
"reviewed_by": "Example reviewer in a fictional exercise",
}
def require(condition: bool, message: str) -> None:
if not condition:
raise ValueError(message)
def validate(proposal: dict) -> None:
service = CATALOG[DISCOVERY["service"]]
require(proposal["client"] == DISCOVERY["client"], "client_differs_from_discovery")
require(proposal["service"] == DISCOVERY["service"], "service_differs_from_discovery")
require(proposal["learners"] == DISCOVERY["learners"], "learners_differ_from_discovery")
require(proposal["learners"] <= service["max_learners"], "group_exceeds_catalog_limit")
require(proposal["format"] == DISCOVERY["format"], "format_differs_from_discovery")
require(proposal["date"] == DISCOVERY["date"], "date_differs_from_discovery")
require(proposal["deliverables"] == service["included"], "unapproved_deliverable")
require(proposal["guarantees"] == [], "guarantees_not_approved")
require(proposal["questions"] == DISCOVERY["unresolved"], "unresolved_questions_missing")
require(bool(proposal["reviewed_by"].strip()), "human_review_required")
try:
price = Decimal(proposal["price_usd"])
catalog_price = Decimal(service["base_usd"])
except (InvalidOperation, TypeError):
raise ValueError("invalid_price") from None
require(price.is_finite() and price == catalog_price, "price_differs_from_catalog")
def render(proposal: dict) -> str:
date = proposal["date"] or "UNCONFIRMED"
included = "\n".join("- " + item for item in proposal["deliverables"])
questions = "\n".join("- " + item for item in proposal["questions"])
return (
f"# Draft proposal for {proposal['client']}\n\n"
"Fictional example. Human commercial approval required before sharing.\n\n"
f"## Objective\n\n{DISCOVERY['requested_goal']}\n\n"
f"## Included\n\n{included}\n\n"
f"Participants: {proposal['learners']}. Format: {proposal['format']}.\n"
f"Date: {date}\nDraft price: USD {Decimal(proposal['price_usd']):.2f}.\n\n"
"## Excluded\n\nNo ongoing support, extra sessions or promised business results.\n\n"
f"## Questions before approval\n\n{questions}\n\n"
"Approval: ____________________ Date: ____________________\n"
)
def rejected(label: str, candidate: dict, expected: str) -> None:
try:
validate(candidate)
except ValueError as error:
require(str(error) == expected, "unexpected_negative_result")
print(f"NEGATIVE {label}=REJECTED {error}")
else:
raise AssertionError("unsafe_proposal_accepted")
def main() -> int:
if len(sys.argv) != 2:
raise SystemExit("usage: python3 -I proposal_check.py OUTPUT_DIR")
output = Path(sys.argv[1])
require(not output.exists(), "output_folder_already_exists")
validate(REVIEWED)
print("BASELINE client=Oak_Learning learners=8 date=UNCONFIRMED")
print("REVIEW price_usd=600.00 deliverables=2 questions=2")
extra = copy.deepcopy(REVIEWED)
extra["deliverables"].append("ongoing support")
rejected("extra_support", extra, "unapproved_deliverable")
dated = copy.deepcopy(REVIEWED)
dated["date"] = "2026-11-10"
rejected("invented_date", dated, "date_differs_from_discovery")
output.mkdir()
(output / "proposal.md").write_text(render(REVIEWED), encoding="utf-8", newline="\n")
print("EXPORT file=proposal.md delivery=not_sent")
print("CHECK PASS")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (ValueError, OSError) as error:
print("ERROR " + str(error), file=sys.stderr)
raise SystemExit(2)
Run python3 -I proposal_check.py results. On Windows, use py -3 -I proposal_check.py results. Complete stdout must match exactly, including the final newline:
BASELINE client=Oak_Learning learners=8 date=UNCONFIRMED
REVIEW price_usd=600.00 deliverables=2 questions=2
NEGATIVE extra_support=REJECTED unapproved_deliverable
NEGATIVE invented_date=REJECTED date_differs_from_discovery
EXPORT file=proposal.md delivery=not_sent
CHECK PASS
The program writes results/proposal.md. It also proves that an added support commitment and an invented date are rejected. It does not call a model, assess prose quality, provide legal review or approve a real proposal.
Failure cases and repair
| Symptom | What happened | Repair |
|---|---|---|
| A date appears even though the note has none | A blank was treated as permission to infer | Restore UNCONFIRMED and ask the client |
| The price becomes USD 4,800.00 | A flat price was multiplied by learner count | Read the catalog rule, then restore USD 600.00 |
| “Ongoing support” appears | The draft added a plausible service | Remove it or obtain a separately approved scope and price |
| A guarantee appears | Promotional prose became a commitment | Remove it and review the whole paragraph for implied promises |
| The document looks complete but has no questions | Unknowns were hidden by fluent prose | Add the unresolved section before approval |
| The assistant route feels faster | Only drafting effort was counted | Record setup, review, repair, failures and maintenance for both routes |
If the assistant output repeatedly changes commitments, roll back to the manual template. Preserve the authoritative notes, discard the unsafe working copy according to your policy and do not send it. A local checker failure should block the export, not encourage you to weaken the check.
For maintenance, review the catalog whenever prices or included services change. Version approved terms. Retest one normal case and the two negative cases after changing the template or checker. A stale rate card is a process defect whether a person or an assistant copies it.
Completion check and next experiment
You are done when another person can open the editable proposal and answer four questions without guessing: Where did the price come from? Which two items are included? What remains unknown? Who must approve before sharing?
For an independent exercise, change the fictional catalog to a USD 900.00 workshop for a maximum of six learners, then request eight learners. The correct result is not a polished proposal. It is a blocked draft with a capacity question. Complete the task manually and with the same assistant instructions. Record setup, drafting, review and repair minutes, any failed attempt, known provider cost and every defect. Only then decide which route deserves a place in your workflow.
The next useful integration is a proposal handoff that creates a draft record in your document system while leaving the send action disabled. Carry the same source fields, unresolved questions and reviewer identity across that boundary. Do not let a successful document export become accidental permission to contact the client.
This issue was produced by an owner-authorized AI editorial workflow. Source inspection, code execution and editorial review were performed by the AI team. No independent human, legal or customer review is claimed. There is no sponsorship or affiliate relationship attached to this issue.