Checks each new enquiry against who you sell to, sends good ones to the right rep in Slack with a reply drafted, and parks the rest.
Uses
Claude
Apollo
Gmail
Google Sheets
HubSpot
Slack
ZeroBounce
Route every new sales enquiry to the right rep
whoYouSellTo to blank.Set whoYouSellTo to blank.whoYouDoNotSellTo to blank.Set whoYouDoNotSellTo to blank.spreadsheetUrl to blank.Set spreadsheetUrl to blank.slackChannelId to blank.Set slackChannelId to blank.bookingLink to blank.Set bookingLink to blank.formNamesThatMeanTalkToSalesNow to Request a demo,Contact sales,Pricing enquiry.Set formNamesThatMeanTalkToSalesNow to Request a demo,Contact sales,Pricing enquiry.replyMode to slack.Set replyMode to slack.replyWithinMinutes to 5.Set replyWithinMinutes to 5.loadedNewLeads to {status:,headers:[],rows:[],count:0}.Set loadedNewLeads to {status:,headers:[],rows:[],count:0}.loadedAccounts to {status:,headers:[],rows:[],count:0}.Set loadedAccounts to {status:,headers:[],rows:[],count:0}.loadedReps to {status:,headers:[],rows:[],count:0}.Set loadedReps to {status:,headers:[],rows:[],count:0}.loadedLedger to {status:,headers:[],rows:[],count:0}.Set loadedLedger to {status:,headers:[],rows:[],count:0}.sheetErrorIf a step below fails, save the error as sheetErrorTry
spreadsheetUrl. Save it as loadedNewLeads.Read the rows of spreadsheetUrl. Save it as loadedNewLeads.spreadsheetUrl. Save it as loadedAccounts.Read the rows of spreadsheetUrl. Save it as loadedAccounts.spreadsheetUrl. Save it as loadedReps.Read the rows of spreadsheetUrl. Save it as loadedReps.spreadsheetUrl. Save it as loadedLedger.Read the rows of spreadsheetUrl. Save it as loadedLedger.On error
sheetError.message.Stop and report a problem: Could not read the lead spreadsheet. It needs four tabs named exactly 'New leads', 'Accounts', 'Reps' and 'Ledger', and the Google Sheets connection must have access to it. Run the 'Inbound lead workspace setup' template to build one correctly. The underlying error was: sheetError.message.freeMailDomains to gmail.com,googlemail.com,yahoo.com,hotmail.com,outlook.com,live.com,aol.com,icloud.com,me.com,proton.me,protonmail.com,gmx.com,mail.com,yandex.com,zoho.com,hey.com.Set freeMailDomains to gmail.com,googlemail.com,yahoo.com,hotmail.com,outlook.com,live.com,aol.com,icloud.com,me.com,proton.me,protonmail.com,gmx.com,mail.com,yandex.com,zoho.com,hey.com.throwawayDomains to mailinator.com,10minutemail.com,guerrillamail.com,tempmail.com,trashmail.com,yopmail.com,sharklasers.com,dispostable.com,maildrop.cc.Set throwawayDomains to mailinator.com,10minutemail.com,guerrillamail.com,tempmail.com,trashmail.com,yopmail.com,sharklasers.com,dispostable.com,maildrop.cc.roleAddressPrefixes to info,sales,support,admin,contact,hello,help,noreply,no-reply,billing,office,team,marketing,careers,jobs,hr,press,legal,webmaster,postmaster.Set roleAddressPrefixes to info,sales,support,admin,contact,hello,help,noreply,no-reply,billing,office,team,marketing,careers,jobs,hr,press,legal,webmaster,postmaster.loadedNewLeads.rows isn't empty and loadedNewLeads.headers doesn't containโฆIf loadedNewLeads.rows isn't empty and loadedNewLeads.headers doesn't containโฆYes
No
No steps
loadedLedger.headers doesn't contain Submission ID or loadedLedger.headersโฆIf loadedLedger.headers doesn't contain Submission ID or loadedLedger.headersโฆYes
No
No steps
loadedNewLeads.rows where item["Submission ID"] isn't blank and item.Email contains @ and save it as leadsWithAnAddress.Keep each item in loadedNewLeads.rows where item["Submission ID"] isn't blank and item.Email contains @ and save it as leadsWithAnAddress.leadsWithAnAddress with loadedLedger.rows, matching by Submission ID and save it as comparedWithLedger.Compare leadsWithAnAddress with loadedLedger.rows, matching by Submission ID and save it as comparedWithLedger.Submission ID from comparedWithLedger.only_in_first and save it as newLeads.Remove duplicates of Submission ID from comparedWithLedger.only_in_first and save it as newLeads.newLeads and save it as leadsThisRun.Take the first 10 items of newLeads and save it as leadsThisRun.newLeads from item 11 on and save it as leadsForNextRun.Take newLeads from item 11 on and save it as leadsForNextRun.loadedLedger.rows where item["Routing Rule"] in lowercase is round robin and save it as earlierRoundRobinLeads.Keep each item in loadedLedger.rows where item["Routing Rule"] in lowercase is round robin and save it as earlierRoundRobinLeads.earlierRoundRobinLeads and save it as roundRobinTurn.Count the items in earlierRoundRobinLeads and save it as roundRobinTurn.leadProblems to an empty list.Set leadProblems to an empty list.routedThisRun to 0.Set routedThisRun to 0.droppedThisRun to 0.Set droppedThisRun to 0.lead in leadsThisRun:For each lead in leadsThisRun:leadErrorIf a step below fails, save the error as leadErrorTry
lead["Submission ID"] and save it as submissionId.Trim lead["Submission ID"] and save it as submissionId.submissionId is emptyIf submissionId is emptyYes
No
No steps
lead.Email lowercase and save it as leadEmail.Make lead.Email lowercase and save it as leadEmail.leadEmail doesn't contain @If leadEmail doesn't contain @Yes
submissionId: no usable email address.Show in the output: Skipped submission submissionId: no usable email address.No
No steps
leadEmail split by @ and save it as emailLocalPart.Get the first item of leadEmail split by @ and save it as emailLocalPart.leadEmail split by @ and save it as emailDomain.Get the last item of leadEmail split by @ and save it as emailDomain.lead.Company and save it as statedCompany.Trim lead.Company and save it as statedCompany.lead.Name and save it as leadName.Trim lead.Name and save it as leadName.lead.Message and save it as leadMessage.Trim lead.Message and save it as leadMessage.lead.Form and save it as formName.Trim lead.Form and save it as formName.statedCompany with , replaced by with . replaced by with Inc replaced by with Ltd replaced by with LLC replaced by lowercase and save it as companyKey.Make statedCompany with , replaced by with . replaced by with Inc replaced by with Ltd replaced by with LLC replaced by lowercase and save it as companyKey.freeMailDomains, contains ,emailDomain, and save it as isFreeMailDomain.Check whether ,freeMailDomains, contains ,emailDomain, and save it as isFreeMailDomain.throwawayDomains, contains ,emailDomain, and save it as isThrowawayDomain.Check whether ,throwawayDomains, contains ,emailDomain, and save it as isThrowawayDomain.roleAddressPrefixes, contains ,emailLocalPart, and save it as isRoleAddress.Check whether ,roleAddressPrefixes, contains ,emailLocalPart, and save it as isRoleAddress.emailStatus to unchecked.Set emailStatus to unchecked.emailTypoSuggestion to blank.Set emailTypoSuggestion to blank.verifyErrorIf a step below fails, save the error as verifyErrorTry
leadEmail. Save it as emailCheck.Verify the email address leadEmail. Save it as emailCheck.emailCheck.status and save it as emailStatus.Trim emailCheck.status and save it as emailStatus.emailCheck.did_you_mean and save it as emailTypoSuggestion.Trim emailCheck.did_you_mean and save it as emailTypoSuggestion.On error
leadEmail - continuing without a deliverability check. verifyError.message.Show in the output: Could not verify leadEmail - continuing without a deliverability check. verifyError.message.loadedAccounts.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain and save it as accountMatches.Keep each item in loadedAccounts.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain and save it as accountMatches.accountMatches is empty and companyKey isn't emptyIf accountMatches is empty and companyKey isn't emptyYes
loadedAccounts.rows where item["Account Name"] in lowercase is companyKey and save it as accountMatches.Keep each item in loadedAccounts.rows where item["Account Name"] in lowercase is companyKey and save it as accountMatches.No
No steps
accountMatches and save it as matchedAccount.Get the first item of accountMatches and save it as matchedAccount.hasAccountMatch to the length of accountMatches is greater than 0.Set hasAccountMatch to the length of accountMatches is greater than 0.accountOwnerEmail to blank.Set accountOwnerEmail to blank.accountOwnerSlackId to blank.Set accountOwnerSlackId to blank.accountIsCustomer to false.Set accountIsCustomer to false.accountHasOpenDeal to false.Set accountHasOpenDeal to false.hasAccountMatch is yesIf hasAccountMatch is yesYes
matchedAccount["Owner Email"] lowercase and save it as accountOwnerEmail.Make matchedAccount["Owner Email"] lowercase and save it as accountOwnerEmail.matchedAccount["Owner Slack ID"] and save it as accountOwnerSlackId.Trim matchedAccount["Owner Slack ID"] and save it as accountOwnerSlackId.accountIsCustomer to matchedAccount["Is Customer"] in lowercase is yes.Change accountIsCustomer to matchedAccount["Is Customer"] in lowercase is yes.accountHasOpenDeal to matchedAccount["Open Opportunity"] in lowercase is yes.Change accountHasOpenDeal to matchedAccount["Open Opportunity"] in lowercase is yes.No
No steps
loadedLedger.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain andโฆ and save it as sameDomainRecently.Keep each item in loadedLedger.rows where isFreeMailDomain is no and item.Domain in lowercase is emailDomain andโฆ and save it as sameDomainRecently.isBuyingGroup to the length of sameDomainRecently is greater than 0.Set isBuyingGroup to the length of sameDomainRecently is greater than 0.enrichedTitle to blank.Set enrichedTitle to blank.enrichedCompany to statedCompany.Set enrichedCompany to statedCompany.enrichedEmployees to blank.Set enrichedEmployees to blank.enrichedIndustry to blank.Set enrichedIndustry to blank.enrichErrorIf a step below fails, save the error as enrichErrorTry
leadEmail. Save it as personEnrichment.Enrich person leadEmail. Save it as personEnrichment.personEnrichment.person.title and save it as enrichedTitle.Trim personEnrichment.person.title and save it as enrichedTitle.On error
leadEmail - judging on the form alone. enrichError.message.Show in the output: Could not look up the person behind leadEmail - judging on the form alone. enrichError.message.isFreeMailDomain is noIf isFreeMailDomain is noYes
orgErrorIf a step below fails, save the error as orgErrorTry
emailDomain. Save it as companyEnrichment.Enrich organization emailDomain. Save it as companyEnrichment.org to companyEnrichment.organization.Set org to companyEnrichment.organization.org.name and save it as enrichedCompany.Trim org.name and save it as enrichedCompany.org.estimated_num_employees and save it as enrichedEmployees.Trim org.estimated_num_employees and save it as enrichedEmployees.org.industry and save it as enrichedIndustry.Trim org.industry and save it as enrichedIndustry.On error
emailDomain. orgError.message.Show in the output: Could not look up the company at emailDomain. orgError.message.No
No steps
enrichedTitle is nullIf enrichedTitle is nullYes
enrichedTitle to blank.Change enrichedTitle to blank.No
No steps
enrichedEmployees is nullIf enrichedEmployees is nullYes
enrichedEmployees to blank.Change enrichedEmployees to blank.No
No steps
enrichedIndustry is nullIf enrichedIndustry is nullYes
enrichedIndustry to blank.Change enrichedIndustry to blank.No
No steps
emailStatus is nullIf emailStatus is nullYes
emailStatus to blank.Change emailStatus to blank.No
No steps
emailTypoSuggestion is nullIf emailTypoSuggestion is nullYes
emailTypoSuggestion to blank.Change emailTypoSuggestion to blank.No
No steps
enrichedCompany is null or enrichedCompany is emptyIf enrichedCompany is null or enrichedCompany is emptyYes
enrichedCompany to statedCompany.Change enrichedCompany to statedCompany.No
No steps
icpFitScore to not scored.Set icpFitScore to not scored.icpFitReason to blank.Set icpFitReason to blank.icpErrorIf a step below fails, save the error as icpErrorTry
enrichedCompany Weโฆ and save it as icpCheck.Run an AI agent: Score how well this company fits our ideal customer profile. Company: enrichedCompany Weโฆ and save it as icpCheck.icpFitScore to icpCheck.output.score.Change icpFitScore to icpCheck.output.score.icpCheck.output.reason and save it as icpFitReason.Trim icpCheck.output.reason and save it as icpFitReason.On error
icpError.message.Show in the output: The company fit check did not run. icpError.message.formNamesThatMeanTalkToSalesNow, in lowercase contains ,formName, in lowercase and save it as isHighIntentForm.Check whether ,formNamesThatMeanTalkToSalesNow, in lowercase contains ,formName, in lowercase and save it as isHighIntentForm.leadDossier to WHO WE SELL TO:Set leadDossier to WHO WE SELL TO:
whoYouSellTo
WHO WE DO NOT SELL TO:
whoYouDoNotSellTo
--- THE ENQUIRY ---
Form: formName plus
High-intent form: isHighIntentForm plus
Name: leadName
Email: leadEmail
Email domain: emailDomain plus
Free-mail address: isFreeMailDomain
Throwaway address: isThrowawayDomain
Role address (info@, sales@): isRoleAddress plus
Deliverability: emailStatus
Company as typed: statedCompany
Company enriched: enrichedCompany
Employees: enrichedEmployees
Industry: enrichedIndustry
Title: enrichedTitle
ICP fit score (0-100, from a separate check): icpFitScore
Already a known account: hasAccountMatch plus
Already a customer: accountIsCustomer
Has an open deal: accountHasOpenDeal
Others from this company enquired recently: isBuyingGroup plus
WHAT THEY WROTE:
leadMessage.triagePrompt to You are triaging one inbound sales enquiry for the sales team described below. Two jobs: decide what this is, and draft the reply.Set triagePrompt to You are triaging one inbound sales enquiry for the sales team described below. Two jobs: decide what this is, and draft the reply.
Judge FIT from the company against WHO WE SELL TO and WHO WE DO NOT SELL TO. Judge INTENT from what the person actually wrote and which form they used. They are different axes: a perfect-fit company idly downloading an ebook is not the same as a poor-fit company demanding a call today, and the two need opposite treatment.
Read the message before anything else. It is the only place that reveals someone is an agency pitching us, a candidate who couldn't find the careers page, a student doing research, or an existing customer who wanted support. Firmographics cannot catch any of those, and all four score well on paper.
Reply in EXACTLY this shape. Every line before the reply delimiter is 'KEY: value' on one line. Do not add commentary, headings or blank lines before the delimiter.
INTENT_CLASS: one of buyer, vendor_pitch, job_seeker, student, existing_customer_support, partner_enquiry, competitor, spam, unclear
FIT_TIER: A, B, C or D. A is squarely in the profile, D is nowhere near.
INTENT_TIER: high, medium or low
CONFIDENCE: a number from 0 to 1
EVIDENCE: one short quote from their message that drove the call. If they wrote nothing usable, put NONE.
REASONING: one sentence a rep can read in three seconds
TEAM_SIZE: a number, or UNKNOWN
TIMELINE: what they said about timing, or UNKNOWN
CURRENT_TOOLING: tools they mentioned, or UNKNOWN
COMPETITOR: a competitor they mentioned switching from, or NONE
---REPLY---
Then the reply itself, written as the rep who will run the call. Open by referencing the specific thing they asked about, in their words, not yours. Say one useful thing. Offer the booking link. Under 90 words, no bullet points, no 'I hope this email finds you well'. If INTENT_CLASS is not buyer, write a short courteous decline or redirect instead - never a sales pitch.
If the enquiry genuinely does not say enough to judge, set INTENT_CLASS to unclear and CONFIDENCE below 0.4 rather than guessing. A person will read those.
Booking link to offer: bookingLink
leadDossier.triagePrompt. Save it as triageResponse.Ask Claude: triagePrompt. Save it as triageResponse.
Maximum response length: 1400triage to {parsed:false,intent_class:unclear,fit_tier:D,intent_tier:low,confidence:0,evidence:,reasoning:"T.Set triage to {parsed:false,intent_class:unclear,fit_tier:D,intent_tier:low,confidence:0,evidence:,reasoning:"T.parseErrorIf a step below fails, save the error as parseErrorTry
raw and save it as triage.Run Python code on raw and save it as triage.On error
leadEmail - routing it to a human instead. parseError.message.Show in the output: Could not read the triage result for leadEmail - routing it to a human instead. parseError.message.intentClass to triage.intent_class.Set intentClass to triage.intent_class.fitTier to triage.fit_tier.Set fitTier to triage.fit_tier.intentTier to triage.intent_tier.Set intentTier to triage.intent_tier.decision to route.Set decision to route.reasonCode to blank.Set reasonCode to blank.needsHumanEye to false.Set needsHumanEye to false.intentClass is spamIf intentClass is spamYes
decision to drop.Change decision to drop.reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.No
No steps
intentClass is vendor_pitchIf intentClass is vendor_pitchYes
decision to drop.Change decision to drop.reasonCode to VENDOR_PITCH.Change reasonCode to VENDOR_PITCH.No
No steps
intentClass is job_seekerIf intentClass is job_seekerYes
decision to drop.Change decision to drop.reasonCode to JOB_SEEKER.Change reasonCode to JOB_SEEKER.No
No steps
intentClass is studentIf intentClass is studentYes
decision to drop.Change decision to drop.reasonCode to STUDENT_OR_RESEARCH.Change reasonCode to STUDENT_OR_RESEARCH.No
No steps
intentClass is competitorIf intentClass is competitorYes
decision to drop.Change decision to drop.reasonCode to COMPETITOR.Change reasonCode to COMPETITOR.No
No steps
intentClass is partner_enquiryIf intentClass is partner_enquiryYes
decision to handoff.Change decision to handoff.reasonCode to PARTNER_ENQUIRY.Change reasonCode to PARTNER_ENQUIRY.No
No steps
intentClass is existing_customer_supportIf intentClass is existing_customer_supportYes
decision to handoff.Change decision to handoff.reasonCode to EXISTING_CUSTOMER.Change reasonCode to EXISTING_CUSTOMER.No
No steps
triage.parsed is no or triage.confidence is less than 0.4If triage.parsed is no or triage.confidence is less than 0.4Yes
needsHumanEye to true.Change needsHumanEye to true.decision to route.Change decision to route.reasonCode to LOW_CONFIDENCE.Change reasonCode to LOW_CONFIDENCE.No
No steps
isThrowawayDomain is yesIf isThrowawayDomain is yesYes
decision to drop.Change decision to drop.reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.No
No steps
,invalid,spamtrap,abuse,do_not_mail, contains ,emailStatus,If ,invalid,spamtrap,abuse,do_not_mail, contains ,emailStatus,Yes
decision to drop.Change decision to drop.reasonCode to INVALID_OR_SPAM.Change reasonCode to INVALID_OR_SPAM.No
No steps
decision is routeIf decision is routeYes
reasonCode is blank and fitTier is A or fitTier is BIf reasonCode is blank and fitTier is A or fitTier is BYes
intentTier is lowIf intentTier is lowYes
decision to nurture.Change decision to nurture.reasonCode to GOOD_FIT_NOT_NOW.Change reasonCode to GOOD_FIT_NOT_NOW.No
reasonCode to PURSUE.Change reasonCode to PURSUE.Else if @reasonCode is blank
intentTier is highIf intentTier is highYes
decision to handoff.Change decision to handoff.reasonCode to LOW_FIT_HIGH_INTENT.Change reasonCode to LOW_FIT_HIGH_INTENT.No
decision to nurture.Change decision to nurture.reasonCode to LOW_FIT.Change reasonCode to LOW_FIT.Otherwise
No steps
No
No steps
routedToName to blank.Set routedToName to blank.routedToEmail to blank.Set routedToEmail to blank.routedToSlackId to blank.Set routedToSlackId to blank.routingRule to blank.Set routingRule to blank.decision is not dropIf decision is not dropYes
accountHasOpenDeal is yes and accountOwnerEmail isn't emptyIf accountHasOpenDeal is yes and accountOwnerEmail isn't emptyYes
routedToEmail to accountOwnerEmail.Change routedToEmail to accountOwnerEmail.routedToSlackId to accountOwnerSlackId.Change routedToSlackId to accountOwnerSlackId.routingRule to open-opportunity owner.Change routingRule to open-opportunity owner.Else if @hasAccountMatch is yes and @accountOwnerEmail isn'โฆ
routedToEmail to accountOwnerEmail.Change routedToEmail to accountOwnerEmail.routedToSlackId to accountOwnerSlackId.Change routedToSlackId to accountOwnerSlackId.routingRule to existing account owner.Change routingRule to existing account owner.Otherwise
No steps
routedToEmail is emptyIf routedToEmail is emptyYes
loadedReps.rows where item.Available in lowercase is not no and item.Email isn't blank and save it as availableReps.Keep each item in loadedReps.rows where item.Available in lowercase is not no and item.Email isn't blank and save it as availableReps.availableReps is emptyIf availableReps is emptyYes
routingRule to no rep available.Change routingRule to no rep available.reasonCode to OWNER_UNAVAILABLE.Change reasonCode to OWNER_UNAVAILABLE.needsHumanEye to true.Change needsHumanEye to true.No
rotationIndex to the remainder of roundRobinTurn divided by the length of availableReps.Set rotationIndex to the remainder of roundRobinTurn divided by the length of availableReps.chosenRep to availableReps[@rotationIndex].Set chosenRep to availableReps[@rotationIndex].chosenRep.Name and save it as routedToName.Trim chosenRep.Name and save it as routedToName.chosenRep.Email lowercase and save it as routedToEmail.Make chosenRep.Email lowercase and save it as routedToEmail.chosenRep["Slack ID"] and save it as routedToSlackId.Trim chosenRep["Slack ID"] and save it as routedToSlackId.routingRule to round robin.Change routingRule to round robin.roundRobinTurn.Add 1 to roundRobinTurn.No
No steps
No
No steps
crmContactId to blank.Set crmContactId to blank.decision is routeIf decision is routeYes
crmLookupErrorIf a step below fails, save the error as crmLookupErrorTry
leadEmail. Save it as crmLookup.Find the contact leadEmail. Save it as crmLookup.crmLookup.id and save it as crmContactId.Trim crmLookup.id and save it as crmContactId.On error
crmCreateErrorIf a step below fails, save the error as crmCreateErrorTry
leadEmail. Save it as crmCreated.Create the contact leadEmail. Save it as crmCreated.crmCreated.id and save it as crmContactId.Trim crmCreated.id and save it as crmContactId.On error
leadEmail was posted and recorded but could not be added to HubSpot, so add them by hand (crmCreateError.message). to the end of leadProblems and save it as leadProblems.Add leadEmail was posted and recorded but could not be added to HubSpot, so add them by hand (crmCreateError.message). to the end of leadProblems and save it as leadProblems.No
No steps
decision in a table and save it as decisionLabel.Look up decision in a table and save it as decisionLabel.fitTier in a table and save it as fitLabel.Look up fitTier in a table and save it as fitLabel.intentTier in a table and save it as intentLabel.Look up intentTier in a table and save it as intentLabel.*@decisionLabel* - @fitLabel, @intentLabel and save it as alertHeadline.Build the text *@decisionLabel* - @fitLabel, @intentLabel and save it as alertHeadline.whoLine to leadName.Set whoLine to leadName.enrichedTitle isn't emptyIf enrichedTitle isn't emptyYes
whoLine to whoLine, enrichedTitle.Change whoLine to whoLine, enrichedTitle.No
No steps
enrichedCompany isn't emptyIf enrichedCompany isn't emptyYes
whoLine to whoLine at enrichedCompany.Change whoLine to whoLine at enrichedCompany.No
No steps
ownerMention to routedToEmail.Set ownerMention to routedToEmail.routedToSlackId isn't emptyIf routedToSlackId isn't emptyYes
<@@routedToSlackId> and save it as ownerMention.Build the text <@@routedToSlackId> and save it as ownerMention.No
No steps
routedToEmail is emptyIf routedToEmail is emptyYes
ownerMention to nobody yet.Change ownerMention to nobody yet.No
No steps
alertBody to alertHeadlineSet alertBody to alertHeadline
whoLine
<mailto:leadEmail|leadEmail> ยท form: formName
> triage.evidence
triage.reasoning
Routed to: ownerMention (routingRule).isBuyingGroup is yesIf isBuyingGroup is yesYes
alertBody to alertBodyChange alertBody to alertBody
:busts_in_silhouette: Someone else from emailDomain also enquired recently - treat this as one buying group.No
No steps
needsHumanEye is yesIf needsHumanEye is yesYes
reasonCode in a table and save it as humanEyeReason.Look up reasonCode in a table and save it as humanEyeReason.@alertBody :eyes: Read this one yourself before replying - @humanEyeReason and save it as alertBody.Build the text @alertBody :eyes: Read this one yourself before replying - @humanEyeReason and save it as alertBody.No
No steps
emailTypoSuggestion isn't emptyIf emailTypoSuggestion isn't emptyYes
alertBody to alertBodyChange alertBody to alertBody
:warning: Possible typo in the address - did they mean emailTypoSuggestion?.No
No steps
decision is not dropIf decision is not dropYes
alertBody to alertBodyChange alertBody to alertBody
*Suggested reply*
triage.reply.slackErrorIf a step below fails, save the error as slackErrorTry
slackChannelId.Send a message to slackChannelId.alertBodyOn error
Lodol. The underlying error was: slackError.message.Stop and report a problem: Could not post to Slack, so nobody would hear about this lead. Check the channel id on the step called 'Create slackChannelId', and make sure the Lodol app has been invited to that channel with /invite Lodol. The underlying error was: slackError.message.routedThisRun.Add 1 to routedThisRun.No
droppedThisRun.Add 1 to droppedThisRun.replyMode in lowercase is draft and decision is routeIf replyMode in lowercase is draft and decision is routeYes
draftErrorIf a step below fails, save the error as draftErrorTry
leadEmail.Draft an email to leadEmail.
Subject: Re: formNametriage.replyOn error
leadEmail was posted to Slack and recorded, but the Gmail draft could not be saved, so reply from the suggested text in Slack (draftError.message). to the end of leadProblems and save it as leadProblems.Add leadEmail was posted to Slack and recorded, but the Gmail draft could not be saved, so reply from the suggested text in Slack (draftError.message). to the end of leadProblems and save it as leadProblems.No
No steps
replyWithinMinutes minutes and save it as replyDueAt.Move the current date and time by replyWithinMinutes minutes and save it as replyDueAt.ledgerErrorIf a step below fails, save the error as ledgerErrorTry
spreadsheetUrl.Add a row to 'Ledger' in spreadsheetUrl.On error
leadEmail (submission submissionId) was handled but could not be added to the 'Ledger' tab. The next run will handle it again, so if it was posted to Slack it will be posted a second time. Check that the Google Sheets connection can edit the spreadsheet and that the 'Ledger' tab is still there. The error was: ledgerError.message.Stop and report a problem: Stopped: leadEmail (submission submissionId) was handled but could not be added to the 'Ledger' tab. The next run will handle it again, so if it was posted to Slack it will be posted a second time. Check that the Google Sheets connection can edit the spreadsheet and that the 'Ledger' tab is still there. The error was: ledgerError.message.On error
lead.Email (submission lead["Submission ID"]) could not be triaged and was not recorded, so the next run tries it again (leadError.message). to the end of leadProblems and save it as leadProblems.Add lead.Email (submission lead["Submission ID"]) could not be triaged and was not recorded, so the next run tries it again (leadError.message). to the end of leadProblems and save it as leadProblems.handledThisRun to routedThisRun plus droppedThisRun.Set handledThisRun to routedThisRun plus droppedThisRun.leadsForNextRun and save it as waitingCount.Count the items in leadsForNextRun and save it as waitingCount.leadProblems isn't emptyIf leadProblems isn't emptyYes
leadProblems with a new line and save it as problemList.Join leadProblems with a new line and save it as problemList.handledThisRun. Some need attention:Stop and report a problem: New leads handled: handledThisRun. Some need attention:
problemList.No
No steps
waitingCount is greater than 0If waitingCount is greater than 0Yes
handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped). Still waiting: waitingCount - they are picked up by the next runs, 10 at a time.Finish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped). Still waiting: waitingCount - they are picked up by the next runs, 10 at a time.No
No steps
handledThisRun is 0If handledThisRun is 0Yes
No
No steps
handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped).Finish the run: New leads handled: handledThisRun (routedThisRun posted to Slack, droppedThisRun dropped).