Reads the pages you name each morning, keeps only the lines matching your brief, and posts them to Slack with their source.
Uses
Claude
Jina AI
Slack
Digest the sources you watch into Slack
Every morning at 08:00, each page you have named, a vendor's changelog, a regulator's notices page, a competitor's blog, is read, and only the lines that match what you care about are kept. Those lines are posted to one Slack channel, each with the address it came from.
Every line posted is quoted from the page word for word: a suggested line that does not appear on the page is dropped and counted, never posted. No summary, ranking or opinion is added, so the judgement stays yours. Exactly one message is posted per run, including on days when nothing matched, so silence is never ambiguous. A page that cannot be read is reported by its host name only, never by the full address, in case it carries a key, and each run is bounded in how many sources it reads and lines it posts.
You need the page addresses to watch, a short brief of what matters to you, and a Slack channel. There is no memory between runs, so a page that says the same thing tomorrow is quoted again.
sourceUrls to blank.Set sourceUrls to blank.readerBrief to blank.Set readerBrief to blank.slackChannelId to blank.Set slackChannelId to blank.maxSourcesPerRun to 8.Set maxSourcesPerRun to 8.maxLinesPerRun to 12.Set maxLinesPerRun to 12.sourceUrls by , and save it as sources.Split sourceUrls by , and save it as sources.keptLines to an empty list.Set keptLines to an empty list.sourcesRead to 0.Set sourcesRead to 0.sourcesSkipped to 0.Set sourcesSkipped to 0.linesRejected to 0.Set linesRejected to 0.source in sources:For each source in sources:source and save it as sourceUrl.Trim source and save it as sourceUrl.sourceUrl is emptyIf sourceUrl is emptykeptLines is greater than or equal to maxLinesPerRun multiplied…If the length of keptLines is greater than or equal to maxLinesPerRun multiplied…sourcesRead is greater than or equal to maxSourcesPerRun multiplied by 1If sourcesRead is greater than or equal to maxSourcesPerRun multiplied by 1sourceUrl doesn't start with http (ignoring case)If sourceUrl doesn't start with http (ignoring case)sourcesSkipped.Add 1 to sourcesSkipped.One entry in 'sourceUrls' is not a web address starting with http, so it was skipped..Show in the output: One entry in 'sourceUrls' is not a web address starting with http, so it was skipped..sourcesRead.Add 1 to sourcesRead.sourceUrl with https:// replaced by with http:// replaced by split by / and save it as sourceHost.Get the first item of sourceUrl with https:// replaced by with http:// replaced by split by / and save it as sourceHost.pageText to blank.Set pageText to blank.pageTitle to blank.Set pageTitle to blank.readErrorIf a step below fails, save the error as readErrorsourceUrl with Jina. Save it as page.Read the page at sourceUrl with Jina. Save it as page.page.content and save it as pageText.Trim page.content and save it as pageText.page.title and save it as pageTitle.Trim page.title and save it as pageTitle.sourceUrl with the source address in readError.message and save it as readNote.Replace sourceUrl with the source address in readError.message and save it as readNote.readNote contains :// (ignoring case)If readNote contains :// (ignoring case)readNote to the page could not be read.Change readNote to the page could not be read.sourceHost: readNote.Show in the output: Could not read sourceHost: readNote.pageText is less than 200If the length of pageText is less than 200sourcesSkipped.Add 1 to sourcesSkipped.sourceHost to filter this run.Show in the output: There was not enough readable text at sourceHost to filter this run.promptIntro to You are filtering one web page for one reader.Set promptIntro to You are filtering one web page for one reader.
The reader cares about:
readerBrief
.prompt to promptIntroReturn at most three lines from the page that match what the reader cares about. Copy each line word for word from the page. Do not summarise it, rewrite it, translate it, rank it, or add any judgement, conclusion or opinion of your own. Separate the lines with |||. If nothing on the page matches, reply with the single word NONE and nothing else.Set prompt to promptIntroReturn at most three lines from the page that match what the reader cares about. Copy each line word for word from the page. Do not summarise it, rewrite it, translate it, rank it, or add any judgement, conclusion or opinion of your own. Separate the lines with |||. If nothing on the page matches, reply with the single word NONE and nothing else.
Page title: pageTitle
Page text:
pageText truncated to 4000 characters.answerText to blank.Set answerText to blank.filterErrorIf a step below fails, save the error as filterErroranswerText.Trim the response text from the Claude “Ask Claude” step and save it as answerText.sourceHost this run, so nothing from it was posted.Show in the output: The filter step did not answer for sourceHost this run, so nothing from it was posted.answerText is emptyIf answerText is emptysuggestedLine in answerText split by |||:For each suggestedLine in answerText split by |||:suggestedLine and save it as candidateLine.Trim suggestedLine and save it as candidateLine.candidateLine is emptyIf candidateLine is emptycandidateLine in lowercase is noneIf candidateLine in lowercase is nonekeptLines is greater than or equal to maxLinesPerRun multiplied…If the length of keptLines is greater than or equal to maxLinesPerRun multiplied…pageText doesn't contain candidateLine (ignoring case)If pageText doesn't contain candidateLine (ignoring case)linesRejected.Add 1 to linesRejected.candidateLine truncated to 300 charactersAdd - candidateLine truncated to 300 characters
sourceUrl to the end of keptLines and save it as keptLines.digestHeader to From the sources you follow - read sourcesRead of them this run.Set digestHeader to From the sources you follow - read sourcesRead of them this run.messageText to digestHeaderSet messageText to digestHeader
Nothing on those pages matched your brief this run.keptLines isn't emptyIf keptLines isn't emptymessageText to digestHeaderChange messageText to digestHeader
keptLines joined by a new line
Every line above is quoted from the page it links to.footer to blank.Set footer to blank.sourcesSkipped is greater than 0If sourcesSkipped is greater than 0footer to Change footer to
sourcesSkipped source(s) could not be read or had too little text to use.linesRejected is greater than 0If linesRejected is greater than 0footer to footerChange footer to footer
linesRejected suggested line(s) were dropped because they did not appear on the page word for word.slackChannelId.Send a message to slackChannelId.messageText plus footer truncated to 3500 characterskeptLines line(s) to Slack from sourcesRead source(s).Show in the output: Posted the length of keptLines line(s) to Slack from sourcesRead source(s).