Reads the official sources you list each day, summarises every new or amended rule, and files a task for each one.

UsesClaudeGoogle SheetsGoogle TasksJina AI

Turn regulatory updates into tracked tasks

Once a day, each official page listed in your Google Sheet, a regulator's news page, a register or a bulletin, is fetched and read, and the AI lists the new or amended rules that page itself describes. Each change becomes one task in the Google Tasks list you name, so a rule change becomes work to tick off rather than a page you meant to check.

Each task is titled with the change and its reference, and its notes give the source, link, effective date and a plain summary of what the change alters. It never says whether a change applies to you, recommends what to do or draws a legal conclusion. A task gets a due date only when the source states an effective date; otherwise the notes say so rather than guessing one. Tasks already in your list, completed ones included, are checked first and any change already there is skipped, so nothing is filed twice.

Your sources sheet needs a 'Source Name' column and a 'Page URL' column, and the Google Tasks list has to exist already.

ScheduleRun every day.Run every day.
ValuesSet sourcesSheetUrl to blank.Set sourcesSheetUrl to blank.
ValuesSet sourcesTabName to Sources.Set sourcesTabName to Sources.
ValuesSet taskListName to blank.Set taskListName to blank.
ValuesSet maxSourcesPerRun to 10.Set maxSourcesPerRun to 10.
ValuesSet maxChangesPerSource to 5.Set maxChangesPerSource to 5.
Google TasksGoogle TasksList lists. Save it as taskLists.List lists. Save it as taskLists.
TextMake taskListName lowercase and save it as wantedListName.Make taskListName lowercase and save it as wantedListName.
ValuesSet taskListId to blank.Set taskListId to blank.
Decisions & LoopsFor each taskList in taskLists.task_lists:For each taskList in taskLists.task_lists:
Decisions & LoopsIf a step below fails, save the error as taskListErrorIf a step below fails, save the error as taskListError
Try
Decisions & LoopsIf taskList.title in lowercase is wantedListNameIf taskList.title in lowercase is wantedListName
Yes
TextTrim taskList.id and save it as taskListId.Trim taskList.id and save it as taskListId.
No
No steps
On error
ValuesShow in the output: Skipped a task list whose name could not be read..Show in the output: Skipped a task list whose name could not be read..
Decisions & LoopsIf taskListId is emptyIf taskListId is empty
Yes
Decisions & LoopsStop and report a problem: No Google Tasks list is called '@taskListName'. Check the name in the 'taskListName' step matches one of your lists exactly.Stop and report a problem: No Google Tasks list is called '@taskListName'. Check the name in the 'taskListName' step matches one of your lists exactly.
No
No steps
Google TasksGoogle TasksList tasks in Google Tasks list taskListId. Save it as existingTasks.List tasks in Google Tasks list taskListId. Save it as existingTasks.
ValuesSet filedTitles to an empty list.Set filedTitles to an empty list.
Decisions & LoopsFor each existingTask in existingTasks.tasks:For each existingTask in existingTasks.tasks:
Decisions & LoopsIf a step below fails, save the error as existingTaskErrorIf a step below fails, save the error as existingTaskError
Try
ListsAdd existingTask.title in lowercase to the end of filedTitles and save it as filedTitles.Add existingTask.title in lowercase to the end of filedTitles and save it as filedTitles.
On error
ValuesShow in the output: Skipped an existing task that has no title..Show in the output: Skipped an existing task that has no title..
TextJoin filedTitles with a new line and save it as alreadyFiled.Join filedTitles with a new line and save it as alreadyFiled.
ValuesSet readingRules to:Set readingRules to:You are reading one page published by an official rule-making or regulatory body. List the new or amended rules that this page itself describes. Rules you must follow exactly: - Report only what is written on this page. Do not add background, context, or anything you know from elsewhere. - Do not say whether a change applies to the reader, do not recommend any action, and do not state any legal conclusion. Describe only what the change alters. - Never invent, infer, estimate or guess a date. Give a date only if this page states one for that change. - If a detail is not on the page, leave it ...
ValuesSet outputFormat to:Set outputFormat to:Output one line per change and nothing else: no heading, no numbering, no blank lines, no closing remarks. Each line must be four fields separated by the pipe character | in this order. Never use a pipe character inside a field. 1. REFERENCE - the identifier this page prints for the change (its number, citation or short code). If the page prints none, use a short distinctive phrase from the change's own title. 2. TITLE - the change's title, in plain text. 3. EFFECTIVE DATE - the date this page states the change takes effect, written as YYYY-MM-DD. If this page does not state one, write exac...
Google SheetsGoogle SheetsRead the rows of sourcesSheetUrl. Save it as sourcesResult.Read the rows of sourcesSheetUrl. Save it as sourcesResult.
Decisions & LoopsFor each source in sourcesResult.rows:For each source in sourcesResult.rows:
Decisions & LoopsIf a step below fails, save the error as sourceErrorIf a step below fails, save the error as sourceError
Try
TextTrim source["Source Name"] and save it as sourceName.Trim source["Source Name"] and save it as sourceName.
TextTrim source["Page URL"] and save it as pageUrl.Trim source["Page URL"] and save it as pageUrl.
ValuesSet rowIsUsable to the length of sourceName is greater than 0 and pageUrl in lowercase starts with http.Set rowIsUsable to the length of sourceName is greater than 0 and pageUrl in lowercase starts with http.
Decisions & LoopsIf rowIsUsable is yesIf rowIsUsable is yes
Yes
Jina AIJina AIRead the page at pageUrl with Jina. Save it as page.Read the page at pageUrl with Jina. Save it as page.
TextShorten page.content to 12000 characters and save it as pageText.Shorten page.content to 12000 characters and save it as pageText.
Decisions & LoopsIf pageText isn't emptyIf pageText isn't empty
Yes
ValuesSet sourceHeader to Source: sourceNameSet sourceHeader to Source: sourceName Page: pageUrl.
ValuesSet prompt to readingRulesSet prompt to readingRules outputFormat sourceHeader Page text: pageText.
ClaudeClaudeAsk Claude: prompt. Save it as reply.Ask Claude: prompt. Save it as reply. Maximum response length: 1500
TextSplit reply.response_text by a new line and save it as changeLines.Split reply.response_text by a new line and save it as changeLines.
ValuesSet filedForSource to 0.Set filedForSource to 0.
Decisions & LoopsFor each changeLine in changeLines:For each changeLine in changeLines:
Decisions & Loops If filedForSource is greater than or equal to maxChangesPerSource multiplied by 1 If filedForSource is greater than or equal to maxChangesPerSource multiplied by 1
Yes
Decisions & LoopsStop repeating.Stop repeating.
No
No steps
Decisions & Loops If a step below fails, save the error as changeError If a step below fails, save the error as changeError
Try
TextSplit changeLine by | and save it as parts.Split changeLine by | and save it as parts.
TextTrim parts[0] and save it as reference.Trim parts[0] and save it as reference.
TextTrim parts[1] and save it as changeTitle.Trim parts[1] and save it as changeTitle.
TextTrim parts[2] and save it as effectiveRaw.Trim parts[2] and save it as effectiveRaw.
TextTrim parts[3] and save it as summary.Trim parts[3] and save it as summary.
ValuesSet marker to [ref: reference].Set marker to [ref: reference].
TextMake marker lowercase and save it as markerKey.Make marker lowercase and save it as markerKey.
ValuesSet worthFiling to the length of reference is greater than 0 and the length of summary is greater than 0 and alreadyFiled contains markerKey is false.Set worthFiling to the length of reference is greater than 0 and the length of summary is greater than 0 and alreadyFiled contains markerKey is false.
Decisions & LoopsIf worthFiling is yesIf worthFiling is yes
Yes
TextExtract the first match from effectiveRaw and save it as effectiveDate.Extract the first match from effectiveRaw and save it as effectiveDate.
ValuesSet dueValue to blank.Set dueValue to blank.
ValuesSet effectiveLine to Effective date: not stated on the source page..Set effectiveLine to Effective date: not stated on the source page..
Decisions & LoopsIf the length of effectiveDate is 10If the length of effectiveDate is 10
Yes
ValuesChange dueValue to effectiveDateT00:00:00.000Z.Change dueValue to effectiveDateT00:00:00.000Z.
ValuesChange effectiveLine to Effective date stated on the source page: effectiveDate.Change effectiveLine to Effective date stated on the source page: effectiveDate.
No
No steps
ValuesSet taskTitle to sourceName truncated to 40 characters: changeTitle truncated to 120 characters marker.Set taskTitle to sourceName truncated to 40 characters: changeTitle truncated to 120 characters marker.
ValuesSet notesTop to Source: sourceNameSet notesTop to Source: sourceName Page: pageUrl.
ValuesSet notesRef to Reference as printed by the source: reference.Set notesRef to Reference as printed by the source: reference.
ValuesSet notesWhat to What the source says: summary.Set notesWhat to What the source says: summary.
ValuesSet notes to notesTopSet notes to notesTop notesRef effectiveLine notesWhat Filed automatically from the page linked above. This is a summary of what that page says and nothing more - it is not legal advice and does not say whether the change applies to you. Read the source before deciding what it means.
Google TasksGoogle TasksCreate task taskTitle in Google Tasks list taskListId.Create task taskTitle in Google Tasks list taskListId. Due date: dueValuenotes
ValuesChange alreadyFiled to alreadyFiledChange alreadyFiled to alreadyFiled markerKey.
ValuesAdd 1 to filedForSource.Add 1 to filedForSource.
No
ValuesShow in the output: Nothing to file for: changeLine.Show in the output: Nothing to file for: changeLine.
On error
ValuesShow in the output: Skipped a line that could not be read: changeLine.Show in the output: Skipped a line that could not be read: changeLine.
No
ValuesShow in the output: No readable text on the page at pageUrl.Show in the output: No readable text on the page at pageUrl.
No
ValuesShow in the output: Skipped a row without a source name or a page link starting with http..Show in the output: Skipped a row without a source name or a page link starting with http..
On error
ValuesShow in the output: Skipped a source row that could not be read: sourceError as text.Show in the output: Skipped a source row that could not be read: sourceError as text.