# GTM workflow spec: Acme signal routing v2 (fictional)

- Status: draft, pilot pending CR-2, CR-3 and a 200-episode dry run. Version: 2. Date: 2026-11-01. Author: agent run for the RevOps lead. Reviewers: VP Sales, privacy lead
- Decision: When a target-fit account shows a qualifying signal (demo or pricing request, trial collaboration milestone or other product event, corroborated web intent, a known contact starting a new role, relevant hiring), the account owner, or an SDR for unowned new business, gets one task or one approved sequence enrollment within the response target, and the outcome returns to the weekly signal review.
- Business owner: VP Sales. Operator: RevOps lead. Stop-control owner: RevOps lead (deputy: sales manager)
- Unit: account for routing, contact for enrollment. Roll-up: one open task per account and play; contacts attach to it.
- Success outcome and window: sales-accepted opportunity within 45 days. Baseline (v1, four reviews): 52% task acceptance.
- Weekly capacity: 2 AE reviewers x 90 minutes / 8 = 22 tasks; SDR sequence capacity 40 new contacts.

## Systems and placement

- Executing system per decision: identity HubSpot (record ID, then email or domain); exclusions Clay, reading a HubSpot snapshot refreshed every 6 hours; enrichment Clay; score HubSpot score properties; route HubSpot workflow "Signal routing"; enrollment Instantly; writeback Clay HubSpot Update object.
- Durable state: Clay table rows hold episodes and the run ledger for the pilot. Move them to the warehouse before a second workflow shares them.
- Read-only design access: HubSpot design user (View, only the design-use read tools allowed); Clay and Instantly CSV exports and screenshots.

## Signals

- S1 Demo and pricing requests, class direct request
  - Event key: `hubspot_forms:sub-<submission ID>`. Identity: email on the form. Clocks: submitted_at, crm_seen_at, first_attempt_at
  - No expiry; an unanswered request is an SLA miss. Action ceiling: human response; never waits for enrichment or a score. Rule version: signals-v3
- S2 Product milestones (trial collaboration milestone, seat limit reached, integration connected, weekly usage), class first-party
  - Event key: `product_events:evt-<event ID>`. Identity: workspace to HubSpot company by unique `acme_workspace_id`
  - Expiry 7 days. Action ceiling: owner task; sequence only for unowned new business through the gate. Checked daily from the warehouse, no vendor cost
- S3 Job change of a known contact, class public change
  - Event key: `clay_job_change:jc-<signal ID>`. Identity: LinkedIn profile URL match. Expiry 90 days from start date; unknown start date: research only
  - Action ceiling: research or owner review; sequence after the gate with a dated source. Cost: 300 contacts checked weekly = 1,200 Actions and 240 Data Credits a month
- S4 Web intent (added in v2), class inferred
  - Event key: `clay_web_intent:ses-<session ID>`. Identity: company domain from IP; never a person. Expiry 14 days
  - Action ceiling: research or owner task; sequence only when corroborated by a person-level first-party fact. Wording: no visit claims
- S5 Hiring (added in v2), class public change
  - Event key: `clay_hiring:post-<posting ID>`. Expiry 30 days from the posting date. Action ceiling: research or owner task

## Identity and exclusions

- Match order: HubSpot record ID, `acme_workspace_id`, normalized primary domain or email. Ambiguous: hold with both IDs. Lookup error: retried 3 times, never "no match".
- Exclusions before any paid step, with reason codes: suppressed (HubSpot subscription status, do-not-contact), customer (lifecycle stage customer), open opportunity (open deal associated), active conversation (Instantly active lead or a human reply in 30 days), internal and test domains (example.com list), competitors and partners (HubSpot list), EU outside the UK (no contact decision).
- Snapshot age at run time: at most 6 hours.
- Reconciliation, pilot run 2026-10-28: 31 records = 1 excluded (customer) + 30 passed to enrichment; the excluded record was enriched anyway (W04, fixed by CR-2).

## Enrichment

- Data points and fields: work email (consumer: sequence enrollment; freshness 30 days validation), job title (consumer: message claim and rep context; 90 days), company size (consumer: fit score; 180 days). No phone numbers: there is no calling step.
- Waterfall, work email: stage 1 provider_a 0.05 USD per returned candidate, misses free; stage 2 provider_b 0.12 USD, misses free; stage 3 provider_c 0.40 USD per lookup, charged on misses (scope under CR-3).
- Acceptance policy: valid with identity matched accepted; accept-all and unknown held (SDR task only); invalid, disposable and identity mismatch rejected. Raw status kept in `enr_email_status`.
- Stop and retry: stop at the first accepted candidate; 3 retries with Retry-After; no fall-through on error; Clay duplicate-result threshold 2.
- Caps: stages 2 and 3 run only through "Only run if" (stage 2 when stage 1 did not accept; stage 3 for tier-1 rows that stages 1 and 2 did not accept). The pilot runs on a filtered view of the 200 approved rows with table auto-run off. Clay MCP rep limit 50 credits. Clay documents no per-record cap and its workbook limits are Enterprise only, so the pilot job's 0.60 USD per record and 50 USD batch limits are checked in the usage Run view and the ledger after the run.
- AI research: not used to gate outreach in v2.

## Scoring

- Gates outside the points: suppressed, customer, open opportunity, active conversation, excluded region.
- Fit (180 days): employee count 50 to 1,000 (15), approved industry (10), data warehouse in technology list (15), served region (10). Engagement (14 days): collaboration milestone (20), two or more identified people active (10), pricing page by an identified contact (5). Excluded: email opens, unidentified page views.
- Unknown: no points, `fit_complete` false, research route.
- Proactive band: fit 35 or more and engagement 20 or more. Band items routed to a sequence or an SDR task in the last 30 days: 7, within the SDR capacity of 40 a week. Tie-breaker: latest signal, then account ID.
- Score version `acme-score-v2` stored on each routed decision.

## Routing

- Precedence: R01 replay, R02 suppressed non-direct, R02a expired evidence to no action, R03 service, R04 customer, R05 open opportunity, R06a unmatched direct request to fallback, R06b unmatched to hold, R06c unknown source date or expiry to research, R07 named owner with covering rep, R08 active conversation, R09a territory missing to fallback, R09 new-business direct request to the AE pool, R10 sequence through the gate, R11 band to SDR task, R12 research, R13 nurture, R99 fallback.
- Pools: ae (AE-1, AE-2) round robin for direct requests; sdr (SDR-1, SDR-2) round robin for the band.
- Availability: HubSpot working hours and out-of-office; covering rep acts, ownership unchanged.
- Response targets: 15 business minutes, backup at 30, team lead at 60.
- Fallback owner: duty rep of the week; escalation after 60 minutes to the sales manager.
- Policy file: `example-acme-routing-policy-v2.json`. Dry run on 2026-09-29 to 2026-10-28 (52 rows, 48 episodes): `0 FAIL, 0 WARN. Nothing was changed.` 48 episodes is below the 200 the procedure requires (kept small for the example); extend the window to 200 episodes before approving the pilot. Test rows proved R02a, R06a, R06c and R99, which the sample never fired.

## Outbound

- Play: sequence acme-signal-intro-v3, segment US and UK mid-market new business, message version 3 approved 2026-10-27 by the sales manager, senders SDR-1 and SDR-2 mailboxes on outreach.example.com, schedule weekdays 09:00 to 16:00 recipient time. Per-mailbox daily limit 30; forecast peak 9 sends a mailbox a day (4 new contacts plus follow-ups to earlier cohorts).
- Gate at enrollment: suppression, customer, open opportunity, active sequence, 30-day reply window, prior hard bounce, validation valid, evidence within expiry, approved message, corroboration for inferred signals.
- Approval scope: the 2026-10-28 audience snapshot, message v3, the two senders and the schedule; expires 2026-11-04 or on any change.
- Enrollment key: contact ID plus play plus episode ID; Instantly lead ID stored back on the Clay row; timeouts reconciled by key before retry.
- Suppression: HubSpot unsubscribes sync to the Instantly Blocklist tab (checked across ongoing campaigns), not a Google Sheets list. AC15 and AC16 passed on 2026-10-30 with controlled inboxes.
- Stops: any human reply, unsubscribe, hard bounce, meeting booked, deal created; out-of-office pauses; company-level stop on reply: yes for this play.
- Replies: the assigned SDR owns replies within 4 business hours; opt-outs act immediately.
- Sender path outreach.example.com: SPF pass, DKIM d=outreach.example.com pass, DMARC pass (p=quarantine), List-Unsubscribe and List-Unsubscribe-Post present on the received test message of 2026-10-30. Postmaster Tools shows no data on most days because recipients are mainly business mailboxes; the substitute signal, opt-outs plus negative replies, was 0.4% of delivered messages over the last 7 days.
- Pause: spam rate 0.1% on any day, batch hard bounces above 2%, opt-outs plus negative replies above 1% of delivered over 7 days, or a placement test to controlled Workspace and Microsoft 365 mailboxes landing in spam; resume after the cause is fixed.

## CRM writeback

- Contract: `example-acme-contract.csv`. Never: hubspot_owner_id, lifecyclestage, hs_lead_status; email, firstname and lastname only on create. Enrichment-owned: enr_company_size, enr_email_status, enr_source, enr_observed_at, candidates. Shared with candidates: jobtitle, phone.
- Update gate: known record ID plus an approved change list. Create gate: zero matches by email, identity evidence, create allowed, serialized per email.
- Blank handling: Clay Update object with Ignore blank values on (CR-2); enr_email_status clears need the RevOps lead's approval.
- Loop prevention: enrichment runs on a new signal, a missing required field or expired freshness, never on record updates; writes only when the value differs.
- Check on the current proposal (blank mode send, as configured today): `14 FAIL, 4 WARN. Nothing was changed.` Not approved. After CR-2 the next proposal must show zero blocked cells.
- Change log: before values per run in the Clay table "writeback log"; rollback by run ID.

## Cost

- Meters: provider data per candidate or lookup, validation 0.005 USD per candidate, Clay Actions inside the plan allowance.
- Fixed allocation: 20 USD per weekly run (plan share). Review time: 2 minutes per accepted record at 60 USD per hour.
- Pilot 2026-10-28, work email: cost per returned candidate 0.055, 0.125 and 1.205 USD by stage; marginal per accepted 0.0733, 0.2083 and 3.615 USD; blended variable 0.2711 USD over 22 accepted.
- Ceiling: 1.00 USD per accepted work email (decisions.md, 2026-09-29). Stage 3 is above it (CR-3).
- Billed reconciliation: provider_a and provider_b match; provider_c billed 12 lookups against 9 modeled (+33.3%), unexplained, blocks scaling.

## Monitoring

- Runbook: monitoring runbook for Acme signal routing (from the template). Stop control: Clay table auto-run off, Instantly campaign paused, HubSpot workflow off; owner RevOps lead; tested 2026-10-30 with a test contact (test01@example.com): step 2 did not send, no Clay run started.
- Weekly review: Mondays, VP Sales, RevOps lead, both SDRs. Expansion after four reviews with zero safety FAILs, acceptance at or above 50% and cost within the model.

## Pilot and acceptance

- Pilot job: 200 records in US and UK mid-market, fields work email, job title and company size, providers a and b (c only for tier-1 if CR-3 keeps it), per-record limit 0.60 USD and batch limit 50 USD checked after the run, no enrollment and no sends during enrichment, approver VP Sales.
- Acceptance: AC01, AC03, AC05, AC06, AC07, AC21, AC22 and AC28 passed on the v2 dry run and test rows (2026-10-30); AC15 to AC17 passed with controlled inboxes, run by the RevOps lead on 2026-10-30; AC11 to AC14 pending CR-2, owner RevOps lead.

## Open decisions

- Contact policy for EU countries outside the UK: privacy lead, by 2026-11-15.
- provider_c scope: tier-1 only or removed: RevOps lead, after the 200-record sample.

## Proposed martech-context updates (not written)

- stack.md: add the Clay table name, the writeback log location and the duty rota.
- decisions.md: record the 6-hour snapshot rule, the 0.60 USD per-record pilot limit, the 1% opt-out and negative-reply pause and the company-level stop for this play.
- data-dictionary.md: add enr_company_size, enr_email_status, enr_source, enr_observed_at, enr_jobtitle_candidate and enr_phone_candidate with owner and writer.
