Emails you a short, sourced briefing on each outside guest booked into your calls in the day ahead.
Uses
Cal.com
Gmail
OpenAI
Serper
Brief yourself on the people you are meeting
Every morning at 07:30, the calls booked for the day ahead are read from Cal.com and the outside guests on them are picked out. Each guest is searched for on the web by name, and you get one email covering everyone you are about to meet, headed with how many people and calls it covers and showing each call's time.
The briefing is written to be checked, not trusted. Every person's note is followed by the search results it came from, with links, and the AI is told to state nothing that a result does not say. Someone the search finds nothing about is reported as having no public information rather than described from guesswork, and if the search itself fails the email says so instead. If every search fails, the run is marked as failed. Your own colleagues are never looked up, a guest booked without a name is skipped, the same person on two calls is covered once, and the number of people researched in one run is capped; the email ends by naming everyone it did not look up and why.
You need Cal.com, Serper (web search), OpenAI and Gmail connected, the address to send the briefing to, and a list of the email domains that count as your own.
briefRecipient to blank.Set briefRecipient to blank.ownEmailDomains to blank.Set ownEmailDomains to blank.lookAheadHours to 24.Set lookAheadHours to 24.maxPeople to 6.Set maxPeople to 6.briefRecipient and save it as recipient.Trim briefRecipient and save it as recipient.recipient doesn't contain @ (ignoring case)If recipient doesn't contain @ (ignoring case)ignoredDomains to an empty list.Set ignoredDomains to an empty list.rawDomain in ownEmailDomains split by ,:For each rawDomain in ownEmailDomains split by ,:rawDomain lowercase and save it as ignoredDomain.Make rawDomain lowercase and save it as ignoredDomain.ignoredDomain is emptyIf ignoredDomain is emptyignoredDomain to the end of ignoredDomains and save it as ignoredDomains.Add ignoredDomain to the end of ignoredDomains and save it as ignoredDomains.windowHours to lookAheadHours multiplied by 1.Set windowHours to lookAheadHours multiplied by 1.windowHours is greater than 168If windowHours is greater than 168windowHours to 168.Change windowHours to 168.windowHours is less than 1If windowHours is less than 1windowHours to 1.Change windowHours to 1.maxPeople to the nearest integer and save it as peopleLimit.Round maxPeople to the nearest integer and save it as peopleLimit.peopleLimit is greater than 15If peopleLimit is greater than 15peopleLimit to 15.Change peopleLimit to 15.peopleLimit is less than 1If peopleLimit is less than 1peopleLimit to 1.Change peopleLimit to 1.booked.List bookings. Save it as booked.sections to an empty list.Set sections to an empty list.coveredEmails to an empty list.Set coveredEmails to an empty list.peopleCount to 0.Set peopleCount to 0.callCount to 0.Set callCount to 0.notLookedUp to an empty list.Set notLookedUp to an empty list.searchFailures to 0.Set searchFailures to 0.lastSearchError to blank.Set lastSearchError to blank.booking in booked.bookings:For each booking in booked.bookings:startsInHours to -1.Set startsInHours to -1.startErrorIf a step below fails, save the error as startErrorbooking.start and save it as startsInHours.Count the hours from the current date and time to booking.start and save it as startsInHours.startsInHours to -1.Change startsInHours to -1.startsInHours multiplied by 1 is less than 0 or startsInHours multiplied by 1…If startsInHours multiplied by 1 is less than 0 or startsInHours multiplied by 1…booking.start readable as “Monday 2:05 PM” and save it as callTime.Make booking.start readable as “Monday 2:05 PM” and save it as callTime.callHasBriefing to false.Set callHasBriefing to false.booking.title and save it as callTitle.Trim booking.title and save it as callTitle.callTitle is empty or callTitle is nullIf callTitle is empty or callTitle is nullcallTitle to Untitled call.Change callTitle to Untitled call.attendee in booking.attendees:For each attendee in booking.attendees:attendee.email lowercase and save it as personEmail.Make attendee.email lowercase and save it as personEmail.personEmail is empty or personEmail is nullIf personEmail is empty or personEmail is nullpersonEmail doesn't contain @ (ignoring case)If personEmail doesn't contain @ (ignoring case)personEmail split by @ and save it as personDomain.Get the last item of personEmail split by @ and save it as personDomain.coveredEmails contains personEmailIf coveredEmails contains personEmailattendee.name and save it as personName.Trim attendee.name and save it as personName.guestLabel to personName.Set guestLabel to personName.personName is empty or personName is nullIf personName is empty or personName is nullguestLabel to personEmail.Change guestLabel to personEmail.ignoredDomains contains personDomainIf ignoredDomains contains personDomainpersonEmail to the end of coveredEmails and save it as coveredEmails.Add personEmail to the end of coveredEmails and save it as coveredEmails.guestLabel (on a domain you said to skip) to the end of notLookedUp and save it as notLookedUp.Add guestLabel (on a domain you said to skip) to the end of notLookedUp and save it as notLookedUp.personName is empty or personName is nullIf personName is empty or personName is nullpersonEmail to the end of coveredEmails and save it as coveredEmails.Add personEmail to the end of coveredEmails and save it as coveredEmails.personEmail (no name on the booking) to the end of notLookedUp and save it as notLookedUp.Add personEmail (no name on the booking) to the end of notLookedUp and save it as notLookedUp.peopleCount is greater than or equal to peopleLimitIf peopleCount is greater than or equal to peopleLimitpersonEmail to the end of coveredEmails and save it as coveredEmails.Add personEmail to the end of coveredEmails and save it as coveredEmails.personName (past the limit of peopleLimit people a run) to the end of notLookedUp and save it as notLookedUp.Add personName (past the limit of peopleLimit people a run) to the end of notLookedUp and save it as notLookedUp.personEmail to the end of coveredEmails and save it as coveredEmails.Add personEmail to the end of coveredEmails and save it as coveredEmails.peopleCount.Add 1 to peopleCount.results to an empty list.Set results to an empty list.searchFailed to false.Set searchFailed to false.searchErrorIf a step below fails, save the error as searchErrorresults to the results from the Serper “Search Google” step.Change results to the results from the Serper “Search Google” step.searchFailed to true.Change searchFailed to true.searchFailures.Add 1 to searchFailures.lastSearchError to searchError.message.Change lastSearchError to searchError.message.sources to blank.Set sources to blank.sourceCount to 0.Set sourceCount to 0.result in results:For each result in results:sourceCount is greater than or equal to 5If sourceCount is greater than or equal to 5result.snippet and save it as resultSnippet.Trim result.snippet and save it as resultSnippet.resultSnippet is emptyIf resultSnippet is emptyresult.title and save it as resultTitle.Trim result.title and save it as resultTitle.result.link and save it as resultLink.Trim result.link and save it as resultLink.sourceLine to - resultTitle: resultSnippet.Set sourceLine to - resultTitle: resultSnippet.sourceLine to sourceLineChange sourceLine to sourceLine
resultLink
.sources to sources plus sourceLine.Change sources to sources plus sourceLine.sourceCount.Add 1 to sourceCount.personHeading to personName <personEmail>.Set personHeading to personName <personEmail>.personHeading to personHeadingChange personHeading to personHeading
Meeting: callTitle, callTime.callHasBriefing to true.Change callHasBriefing to true.searchFailed is yesIf searchFailed is yespersonHeadingAdd personHeading
The web search for this person failed (lastSearchError), so nothing was looked up. That is not the same as there being nothing to find. to the end of sections and save it as sections.sourceCount is 0If sourceCount is 0personHeadingAdd personHeading
No public information was found for this person, so there is nothing to brief. to the end of sections and save it as sections.personPrompt to You are writing two or three sentences about ONE person, for someone who is about to meet them.Set personPrompt to You are writing two or three sentences about ONE person, for someone who is about to meet them.
Rules you must follow, without exception:
- Use ONLY the search results below. Every statement you write must be supported by one of them.
- Do not state a job title, an employer, a history or anything else unless a result below states it.
- Do not guess anything from the person's email address.
- If the results below look like they are about a different person with a similar name, write only: 'The search results do not clearly match this person.'
- Write nothing about their personal life, family, health, politics or beliefs, even if a result mentions it.
- No advice, no opinions, no suggested talking points.
- Plain text. No markdown, asterisks or hash marks.
Person: personName.personPrompt to personPromptChange personPrompt to personPrompt
Email domain: personDomain.personPrompt to personPromptChange personPrompt to personPrompt
Search results:
sources.note to blank.Set note to blank.modelErrorIf a step below fails, save the error as modelErrornote.Trim the response text from the OpenAI “Ask OpenAI” step and save it as note.personName.Show in the output: No briefing could be written for personName.note is empty or note is nullIf note is empty or note is nullnote to No briefing was written for this person this run. The sources found are listed below - read them yourself..Change note to No briefing was written for this person this run. The sources found are listed below - read them yourself..section to personHeadingSet section to personHeading
note truncated to 1500 characters using as the ellipsis.section to sectionChange section to section
What this is based on:
sources.section to the end of sections and save it as sections.Add section to the end of sections and save it as sections.callHasBriefing is yesIf callHasBriefing is yescallCount.Add 1 to callCount.notLookedUpLine to blank.Set notLookedUpLine to blank.emailClosing to blank.Set emailClosing to blank.notLookedUp isn't emptyIf notLookedUp isn't emptynotLookedUp with , and save it as notLookedUpNames.Join notLookedUp with , and save it as notLookedUpNames.Not looked up: @notLookedUpNames. and save it as notLookedUpLine.Build the text Not looked up: @notLookedUpNames. and save it as notLookedUpLine.emailClosing to Change emailClosing to
----------
notLookedUpLine.sections is emptyIf sections is emptynotLookedUpLine.Finish the run: Nobody outside your own domains could be looked up in the window ahead, so no briefing was sent. notLookedUpLine.peopleWord to people.Set peopleWord to people.peopleCount is 1If peopleCount is 1peopleWord to person.Change peopleWord to person.callWord to calls.Set callWord to calls.callCount is 1If callCount is 1callWord to call.Change callWord to call.headline to peopleCount peopleWord across callCount callWord in the next windowHours hours.Set headline to peopleCount peopleWord across callCount callWord in the next windowHours hours.emailIntro to headline.Set emailIntro to headline.
Here is what public web sources say about them.emailIntro to emailIntroEvery line comes from the sources quoted beneath it, and where nothing was found it says so. Check anything you plan to repeat out loud.Change emailIntro to emailIntroEvery line comes from the sources quoted beneath it, and where nothing was found it says so. Check anything you plan to repeat out loud.sections with "Join sections with
----------
and save it as allSections.emailIntro, allSections, emailClosing] with nothing and save it as emailBody.Join [emailIntro, allSections, emailClosing] with nothing and save it as emailBody.emailSubject to Who you are meeting: headline.Set emailSubject to Who you are meeting: headline.recipient.Send an email to recipient.
Subject: emailSubjectemailBodysearchFailures is greater than 0 and searchFailures is peopleCountIf searchFailures is greater than 0 and searchFailures is peopleCountlastSearchError), so the briefing that was sent has no research in it. Check your Serper connection under Integrations, then run it again.Stop and report a problem: Every web search failed (Serper said: lastSearchError), so the briefing that was sent has no research in it. Check your Serper connection under Integrations, then run it again.headline.Show in the output: Emailed a briefing covering headline.