quote-followup
Once-daily check-in for quotes the shop sent but hasn't heard back on. Finds QuoteLog rows where status is quoted and received_at is older than the configured threshold (default 7 days), sends a polite follow-up email to the customer, and stamps the row followed-up so the same quote isn't chased again. Processes all eligible rows in one run; small-shop volume is low and these are different customers each time. Pure deterministic — no AI.
Use case
The quotes that get won are usually the ones the shop chased on day 7 or 8. Owners know this, but the chasing is the thing that always slips: the owner is on the floor, the estimator is on the next quote, and the open quotes drift past the chase window. This workflow replaces the discipline with a cron — one polite email per stale quote, every day, automatic.
The follow-up text is a fixed template; the shop owns the wording. Single follow-up per quote (status moves to followed-up); two-pass follow-up is a customization, not built in by default.
Setup
- Credentials (Credentials view):
-
google-workspace— same one the other workflows use - Runtime environment (Runtime Environments view):
-
bash— InTouch auto-creates this on Linux/macOS install from/bin/bash. Must includebash,python3, and thegogCLI on PATH. - Windows: InTouch auto-createspowershellandcommand promptinstead. To run this workflow on Windows: install Git Bash or WSL and add abashruntime env in InTouch pointing at it (e.g.C:\Program Files\Git\bin\bash.exe), OR changeruntimeEnvName: "bash"to"powershell"inworkflow.yamland rewrite thescriptblock in PowerShell. - QuoteLog Sheet — the same one rfq-triage writes to. Status column K drives this workflow's behavior:
-
new— RFQ logged, no quote sent yet (skipped) -quoted— shop sent the quote (manual transition by the estimator) -followed-up— set by this workflow after one check-in (skipped going forward) -won/lost/expired/cancelled/withdrawn— terminal (skipped) - Manual transition the shop has to make: when the estimator sends a quote, update the QuoteLog row's status from
newtoquoted. That's the signal this workflow watches for. The cleanest way: have the estimator paste the REF_ID into the quote email's subject and update the row's status when they hit send. - Edit
workflow.yaml— replace the three placeholders: -<<QUOTE_LOG_SHEET_ID>>— QuoteLog spreadsheet ID -<<SHOP_NAME>>— your shop's name for the email signature -<<FOLLOWUP_AFTER_DAYS>>— integer, days sincereceived_atbefore sending the follow-up (e.g.7) - Schedule the workflow once daily —
8:00 AMis the convention (after shop-status-digest).
Pipeline
- followup —
runtimeenv(bash + gog + python3). ReadsQuoteLog!A2:K. For each row where status isquotedandreceived_atis more than N days old: sends a templated follow-up email to the customer'sfrom_email, then updates the row's status tofollowed-up. Order matters — send first, update second — so a Sheets-update failure can't cause a missed email; worst case is a duplicate send next day, which is recoverable.
Email template (default)
Subject: Following up on quote RFQ-20260503-091014
Hi Acme Aerospace,
I wanted to follow up on the quote we sent you for housing assembly Rev C
(reference RFQ-20260503-091014). It's been 8 days, and I wanted to check
whether you have any questions or if there's anything more you need from
us to move forward.
Happy to walk through pricing, lead time, or any technical details whenever
it works for you.
— Your Shop Name
Customer name is the customer field from the QuoteLog (parsed from the original RFQ by the AI in rfq-triage). Project name is the project field. Days elapsed is computed from received_at to today.
Customization
- Threshold —
<<FOLLOWUP_AFTER_DAYS>>. Common values:5(aggressive),7(standard),10(patient). - Email wording — edit the
body = (...)block infollowup. Keep{ref_id},{project},{customer},{elapsed},{shop}available. - Two-pass follow-up — add a fourth status
followed-up-2after the first cycle. Change the script to also matchfollowed-uprows where now − the followup date is more than N more days, sending a second email and moving status tofollowed-up-2. Requires tracking the followup date — either parse the row's most-recent update from Gmail history, or add a 12th column to the Sheet. - CC the estimator or owner — add
--cc [email protected]to thegmail sendsubprocess call. - Thread the follow-up with the original quote thread — requires storing the Gmail
thread_idon the QuoteLog row when the original quote is sent. Add a 12th column and pass--thread-id "{tid}"to thegmail sendcall. - Different language by urgency — branch on the row's
urgencycolumn (J): rush quotes might warrant a stronger tone. - Skip terminal states explicitly — already implicit: only
status == "quoted"is matched. The status column doubles as the "have we followed up yet" flag.
Companion workflows
rfq-triage— writes the QuoteLog this workflow readsshop-status-digest— countsquotedrows withreceived_at >7dago as "stale" in the morning digest; quote-followup is the action layer that resolves them
Verified
gog sheets get, sheets update, gmail send flag/command syntax verified against the bundled gog v0.19.0 (2026-06-01); re-verify output shapes on first run. No new dependencies beyond the existing google-workspace credential and bash runtime env.
Source
See workflow.yaml.