| name | sales-proposal |
| description | Use whenever a used-machinery dealer needs a branded sales proposal or purchase offer PDF for a client. Direction-aware — the dealer can be the SELLER (proposal → their buyer) or BUYER (offer → the seller); payment terms and legal framing flip automatically. Built for blind co-broker deals (e.g. ABC Equipment has the seller, reaches the dealer who has the buyer, dealer never inspects the machine). Includes maximum-protection AS-IS / blind-purchase legal language, payment terms (wire-on-PO, deposit, net-terms), itemized costs, and rigging/freight either as line items (if the dealer arranges them) or as recommendations (if they don't). Auto-loads brand from .imm_brand.json and sales terms (default payment terms, per-customer credit terms, custom boilerplate) from .dealer_sales_terms.json. Triggers on "build a sales proposal", "make a purchase offer", "proposal for [customer]", "quote this machine to my buyer", or "offer on this machine". NOT for freight rate quotes — this is the equipment sale itself. |
Sales Proposal / Purchase Offer
Generates a branded, legally-protective PDF for selling or buying used machinery. Built around the blind co-broker reality: the dealer is often a middle party who never sees the machine, so the default legal posture is maximum protection.
When this fires
- "Build a sales proposal for [machine] to [customer]"
- "Make a purchase offer on this machine"
- "Quote this machine to my buyer"
- "I've got a buyer for the Krauss-Maffei, send them a proposal"
- "Offer ABC Equipment $31k for the Engel"
- Any request for the equipment-sale paperwork (NOT a freight rate quote)
First-run setup (asked once, cached)
If .dealer_sales_terms.json doesn't exist, run setup. Ask the dealer (this can happen during IMM agent onboarding):
- Default payment terms — the majority case. Options:
wire_on_po — Wire on PO, machine released on cleared funds (common default)
100_upfront — 100% upfront before shipment
50_50 — 50% deposit / 50% before release
net_terms — Net 15/30 for approved accounts
- Credit customers — "Do you extend credit terms to specific customers? If yes, who, and what terms?" Store each by name so the skill auto-applies their terms when that customer is the counterparty.
- Custom boilerplate — "Any of your own machine-selling language to always include?" Store it; it's appended after the generated standard terms.
- Governing state — for the governing-law clause (defaults to the dealer's state).
Write all of this to /mnt/user-data/uploads/.dealer_sales_terms.json:
{
"default_payment_kind": "wire_on_po",
"net_days": 30,
"credit_customers": {
"Midwest Molding Co.": {"kind": "net_terms", "net_days": 30, "note": "Approved 2025"}
},
"custom_boilerplate": "All sales coordinated through ...",
"governing_state": "Indiana",
"as_is_strength": "maximum",
"validity_days": 30,
"currency": "USD"
}
Per-proposal flow (asked each time)
- Direction — "Are you the SELLER (proposal → your buyer) or the BUYER (offer → the seller)?"
sell → document titled "Sales Proposal", dealer = seller in all legal language
buy → document titled "Purchase Offer", dealer = buyer
- Counterparty — name, contact, address, email, phone. If the name matches a stored credit customer, their terms auto-apply (mention this to the dealer).
- Machine — title, year, serial, condition, location, description.
- Pricing — the machine price plus any other line items.
- Rigging & trucking — three modes:
included → dealer arranges them; add as line items (rigging, freight). Liability note shifts risk to the service providers.
recommendations → dealer doesn't provide them; collect 1-3 recommended providers, printed as referrals-only (no warranty, no compensation).
none → omit entirely.
- Blind purchase? — default YES for co-broker deals. Adds the Intermediary/Blind Transaction disclosure (dealer hasn't inspected; buyer arranges own inspection).
Build
import sys
sys.path.insert(0, 'scripts')
from build_proposal import build_proposal
build_proposal(
output_path="/mnt/user-data/outputs/proposal_<machine>.pdf",
direction="sell",
counterparty={
"name": "Midwest Molding Co.",
"contact": "Attn: Purchasing",
"address": "4400 Industrial Pkwy, Columbus, OH 43204",
"email": "purchasing@midwest-molding.example",
"phone": "(614) 555-0188",
},
machine={
"title": "Krauss-Maffei CX 160 Injection Molding Machine",
"description": "160-ton hydraulic toggle-clamp IMM. Sourced from a third-party holder.",
"year": "2008", "serial": "KM-CX160-08842",
"condition": "Used — as represented by source",
"location": "Currently at originating facility",
},
line_items=[
{"desc": "Krauss-Maffei CX 160", "sub": "Sold as-is", "qty": 1, "unit_price": 42500},
],
rigging_mode="included",
rigging_items=[
{"desc": "Rigging & Load-out", "sub": "At originating facility", "qty": 1, "unit_price": 2800},
{"desc": "Freight", "sub": "Step-deck, tarped", "qty": 1, "unit_price": 3400},
],
blind_purchase=True,
)
The function pulls brand + terms from the caches automatically. Pass terms_override / brand_override only for testing or one-off changes.
What the PDF contains
Page 1 — Pricing: branded header, machine title + metadata, FROM/TO party cards (labeled SELLER/BUYER per direction), description, itemized line table with rigging/freight, totals, validity date.
Page 2+ — Terms: Payment clause, the red Condition & Warranty (AS-IS) block, Blind Transaction disclosure (if blind), Rigging & Freight note, full standard terms (title/risk of loss, cancellation, removal/storage, pricing validity, taxes, governing law, entire agreement), the dealer's custom boilerplate, dual signature lines, and a "not legal advice" disclaimer.
The legal posture (default = maximum protection)
For blind co-broker deals the default AS-IS clause is the strongest version: no inspection, no warranties express or implied, no merchantability/fitness, buyer waives all claims, NO RETURNS/REFUNDS/RECOURSE. This protects the dealer who never touched the machine. The dealer can downgrade to as_is_strength: "standard" in their terms cache, or edit any clause.
Clauses live in scripts/legal_clauses.py and are fully editable. Always remind the dealer this is industry-standard language, not legal advice — their counsel owns the final terms.
Anti-patterns
- ❌ Defaulting to a weak warranty clause on a blind deal — the dealer's exposure is real; default strong.
- ❌ Forgetting to flip seller/buyer when direction is "buy" — the legal language must name the right party as warrantor.
- ❌ Auto-applying credit terms without telling the dealer — surface it ("Midwest Molding is on file for Net 30; applying that").
- ❌ Adding rigging as a line item when the dealer doesn't provide it — use recommendations mode instead.
- ❌ Presenting the proposal as legally binding/vetted — it's a commercial document; counsel reviews.
File map
scripts/build_proposal.py — the PDF builder (direction-aware, brand+terms aware)
scripts/legal_clauses.py — editable clause library (as-is, payment, boilerplate, rigging)
references/setup_questions.md — the first-run questionnaire reference
Companion skills
imm-spec-agent — sets up the shared brand cache; the spec sheet pairs with this proposal
- (freight rate-quote skills, if installed separately) — different document type; this skill is the equipment sale itself