<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paopao Studio</title>
    <description>The latest articles on DEV Community by Paopao Studio (@paopaostudio).</description>
    <link>https://dev.to/paopaostudio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4216264%2F38f386f9-30e6-4746-946a-980c0feb527a.jpg</url>
      <title>DEV Community: Paopao Studio</title>
      <link>https://dev.to/paopaostudio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paopaostudio"/>
    <language>en</language>
    <item>
      <title>I scanned 2,056 public n8n templates: 172 of them call an OpenAI or Anthropic model/API that is already shut down</title>
      <dc:creator>Paopao Studio</dc:creator>
      <pubDate>Sat, 31 Oct 2026 02:25:30 +0000</pubDate>
      <link>https://dev.to/paopaostudio/i-scanned-2056-public-n8n-templates-172-of-them-call-an-openai-or-anthropic-modelapi-that-is-4jhd</link>
      <guid>https://dev.to/paopaostudio/i-scanned-2056-public-n8n-templates-172-of-them-call-an-openai-or-anthropic-modelapi-that-is-4jhd</guid>
      <description>&lt;p&gt;If you import an n8n template from a year ago, the workflow JSON often doesn't tell you which model it will call. When a parameter equals its default, n8n leaves it out of the export, so the model is decided by the node type, its &lt;code&gt;typeVersion&lt;/code&gt; and the n8n release that runs it. Some nodes go further and &lt;strong&gt;hardcode&lt;/strong&gt; the model (the OpenAI node's audio transcribe/translate operations always send &lt;code&gt;whisper-1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I wanted to know how many public templates point at models or APIs that OpenAI and Anthropic have already shut down. So I wrote a small offline scanner and ran it over a public template collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I scanned (and what I didn't)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/felipfr/awesome-n8n-workflows" rel="noopener noreferrer"&gt;&lt;code&gt;felipfr/awesome-n8n-workflows&lt;/code&gt;&lt;/a&gt;, a third-party, MIT-licensed mirror of n8n workflow templates, at commit &lt;code&gt;8aa4a25&lt;/code&gt; (2025-08-08). &lt;strong&gt;This is not n8n's official template library&lt;/strong&gt;, and the mirror has no per-template dates, so I can't tell how old each template is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates:&lt;/strong&gt; 2,056 workflow files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"AI templates":&lt;/strong&gt; 804 of those contain &lt;code&gt;openai&lt;/code&gt;, &lt;code&gt;anthropic&lt;/code&gt;, &lt;code&gt;lmChat&lt;/code&gt; or &lt;code&gt;api.openai.com&lt;/code&gt; anywhere in the file (case-insensitive). This is a plain text match, so treat it as a rough denominator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference date:&lt;/strong&gt; 2026-10-31. "Already shut down" means the provider's shutdown date is on or before that day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rules:&lt;/strong&gt; only &lt;strong&gt;verified&lt;/strong&gt; rules, where the model ID and the shutdown date appear on the official &lt;a href="https://developers.openai.com/api/docs/deprecations" rel="noopener noreferrer"&gt;OpenAI deprecations page&lt;/a&gt; or the &lt;a href="https://platform.claude.com/docs/en/about-claude/model-deprecations" rel="noopener noreferrer"&gt;Anthropic model deprecations page&lt;/a&gt;. Both pages were checked on 2026-10-31.&lt;/li&gt;
&lt;li&gt;These are &lt;strong&gt;templates, not running workflows&lt;/strong&gt;. A template that uses a retired model tells you what people will copy, not what is in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Headline numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Templates scanned&lt;/td&gt;
&lt;td&gt;2,056&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI templates (text match)&lt;/td&gt;
&lt;td&gt;804&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Templates with at least one finding from a verified rule (already shut down or scheduled)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;346&lt;/strong&gt; (16.83% of all, 43.03% of AI templates)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Templates with at least one verified finding that is &lt;strong&gt;already shut down&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;172&lt;/strong&gt; (21.39% of AI templates)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So roughly one in five AI templates in this mirror would call something that no longer exists if you imported it today and ran it as-is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the 172 "already shut down" templates use
&lt;/h2&gt;

&lt;p&gt;Counts are templates per model. One template can use several models, so the rows add up to more than 172. "Explicit" means the model ID is written in the JSON. "Default" means the model field is missing and n8n's default for that node and &lt;code&gt;typeVersion&lt;/code&gt; applies. "Hardcoded" means n8n sets the model in code. A template can count in both "explicit" and "default" if it has several nodes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model / API&lt;/th&gt;
&lt;th&gt;Shutdown date&lt;/th&gt;
&lt;th&gt;Templates&lt;/th&gt;
&lt;th&gt;Explicit&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Hardcoded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dall-e-3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-05-12&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assistants API&lt;/td&gt;
&lt;td&gt;2026-08-26&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo-instruct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-09-28&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-turbo-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-03-26&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-3-5-sonnet-20240620&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2025-10-28&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-3-5-haiku-20241022&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-02-19&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-image-1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-vision-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2024-12-06&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-1106-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo-1106&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-09-28&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chatgpt-4o-latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-02-17&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dall-e-2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-05-12&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text-davinci-edit-001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2024-01-04&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-3-7-sonnet-20250219&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-02-19&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4.1-nano&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o3-mini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-3-5-sonnet-20241022&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2025-10-28&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo-0301&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2024-09-13&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo-16k-0613&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2024-09-13&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-32k-0314&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2025-06-06&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4o-2024-05-13&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4.5-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2025-07-14&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4-0125-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-03-26&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-3.5-turbo-0125&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4.1-nano-2025-04-14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o3-mini-2025-01-31&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-10-23&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few of these are only visible if you know n8n's defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dall-e-3&lt;/code&gt; (23 of 27 by default).&lt;/strong&gt; The OpenAI node's &lt;em&gt;Image → Generate&lt;/em&gt; operation defaults to &lt;code&gt;dall-e-3&lt;/code&gt; before &lt;code&gt;typeVersion&lt;/code&gt; 2.2, and the default isn't saved in the JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;claude-3-5-sonnet-20240620&lt;/code&gt; (11 of 11 by default).&lt;/strong&gt; This is the Anthropic Chat Model default at &lt;code&gt;typeVersion&lt;/code&gt; 1.2. None of these templates contain the string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gpt-4-vision-preview&lt;/code&gt; (7 hardcoded).&lt;/strong&gt; In older versions of the OpenAI node (&lt;code&gt;typeVersion&lt;/code&gt; below 1.4), &lt;em&gt;Image → Analyze&lt;/em&gt; has it hardcoded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assistants API (24).&lt;/strong&gt; These come from the OpenAI node's &lt;em&gt;Assistant&lt;/em&gt; resource, the old &lt;em&gt;OpenAI Assistant&lt;/em&gt; node, or HTTP calls to &lt;code&gt;/v1/assistants&lt;/code&gt; and &lt;code&gt;/v1/threads&lt;/code&gt;. The API itself was shut down, so changing the model doesn't help. Those workflows need to move to the Responses API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gpt-3.5-turbo&lt;/code&gt;, &lt;code&gt;gpt-3.5-turbo-instruct&lt;/code&gt;, &lt;code&gt;text-davinci-edit-001&lt;/code&gt; and &lt;code&gt;dall-e-2&lt;/code&gt; (defaults).&lt;/strong&gt; These come from the legacy &lt;code&gt;n8n-nodes-base.openAi&lt;/code&gt; node and the OpenAI LLM node. The 2 default &lt;code&gt;gpt-3.5-turbo-1106&lt;/code&gt; templates come from the old &lt;em&gt;OpenAI Assistant&lt;/em&gt; node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scheduled, not yet shut down
&lt;/h2&gt;

&lt;p&gt;These are the verified rules whose shutdown date is after 2026-10-31.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model / API&lt;/th&gt;
&lt;th&gt;Shutdown date&lt;/th&gt;
&lt;th&gt;Templates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5-mini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-12-11&lt;/td&gt;
&lt;td&gt;133 (all from the OpenAI Chat Model default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;whisper-1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-02-26&lt;/td&gt;
&lt;td&gt;39 (33 hardcoded by n8n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4o-2024-08-06&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-14&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tts-1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-06&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4o-mini-2024-07-18&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-14&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/v1/audio/translations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-02-26&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4.1-mini-2025-04-14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-14&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4o-2024-11-20&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-14&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-4.1-2025-04-14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-01-14&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;gpt-5-mini&lt;/code&gt; row needs care. The OpenAI Chat Model node's default changed &lt;strong&gt;without a &lt;code&gt;typeVersion&lt;/code&gt; bump&lt;/strong&gt;: it was &lt;code&gt;gpt-4o-mini&lt;/code&gt;, then &lt;code&gt;gpt-4.1-mini&lt;/code&gt;, and since n8n PR #24342 (merged 2026-01-15) it is &lt;code&gt;gpt-5-mini&lt;/code&gt;. The 133 count assumes the template runs on a current n8n release. On an older release the same node sends a different model.&lt;/p&gt;

&lt;p&gt;The 33 hardcoded &lt;code&gt;whisper-1&lt;/code&gt; templates can't be fixed from the node UI. You either replace the node with an HTTP Request node or wait for n8n to change the operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately did not count
&lt;/h2&gt;

&lt;p&gt;The official pages list &lt;strong&gt;dated snapshots&lt;/strong&gt; such as &lt;code&gt;gpt-4o-2024-08-06&lt;/code&gt; and &lt;code&gt;gpt-4o-mini-2024-07-18&lt;/code&gt;. Many templates use the &lt;strong&gt;undated aliases&lt;/strong&gt; instead: &lt;code&gt;gpt-4o&lt;/code&gt;, &lt;code&gt;gpt-4o-mini&lt;/code&gt;, &lt;code&gt;gpt-4.1&lt;/code&gt;, &lt;code&gt;gpt-4.1-mini&lt;/code&gt;. I could not find an official statement that gives those aliases a shutdown date. Mapping an alias to a retiring snapshot would be my own inference, so none of the numbers above count them.&lt;/p&gt;

&lt;p&gt;The scanner still knows about them, but as &lt;strong&gt;unverified&lt;/strong&gt; rules. They are only reported if you pass &lt;code&gt;--include-unverified&lt;/code&gt;, and then they are marked as unverified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Third-party mirror.&lt;/strong&gt; It is not n8n's library and has no template dates, and the snapshot is from 2025-08-08.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text-match denominator.&lt;/strong&gt; The 804 "AI templates" figure comes from a text match, not a semantic classification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default inference.&lt;/strong&gt; Default-model findings rely on n8n's current source (pinned commit). Each finding in the report links to the line that defines the default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precision, recall and bias.&lt;/strong&gt; I measured precision and recall on a hand-labelled sample, with a dev set plus a small random holdout. I also labelled them myself, so the labels share my reading of n8n's defaults. The numbers and that bias are spelled out in the repo README.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example strings.&lt;/strong&gt; Model IDs that appear only inside example data (for example a "Set input data" node with a sample payload) can show up as false positives.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check your own workflows
&lt;/h2&gt;

&lt;p&gt;The scanner is a single Python file with one dependency (PyYAML). It works offline and never modifies your files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/paopao-studio-ai/model-sunset-scanner model-sunset-scanner
&lt;span class="nb"&gt;cd &lt;/span&gt;model-sunset-scanner
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# n8n: Workflow menu -&amp;gt; Download, or `n8n export:workflow --all --separate --output=./flows/`&lt;/span&gt;
python3 model_sunset_scan.py ./flows/ &lt;span class="nt"&gt;--md&lt;/span&gt; report.md

&lt;span class="c"&gt;# Make: scenario -&amp;gt; Export Blueprint&lt;/span&gt;
python3 model_sunset_scan.py my_scenario.blueprint.json

&lt;span class="c"&gt;# Any code or config&lt;/span&gt;
python3 model_sunset_scan.py ./src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each finding shows the node, the JSON path, the shutdown date, the official replacement and, where the provider documents it, which request parameters change, such as &lt;code&gt;temperature&lt;/code&gt; on newer reasoning models or &lt;code&gt;max_tokens&lt;/code&gt; → &lt;code&gt;max_completion_tokens&lt;/code&gt;. The exit code is 1 when anything is found, so you can run it in CI.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/paopao-studio-ai/model-sunset-scanner" rel="noopener noreferrer"&gt;https://github.com/paopao-studio-ai/model-sunset-scanner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Need help migrating? &lt;a href="https://paopao-studio.pages.dev/?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=model_sunset" rel="noopener noreferrer"&gt;https://paopao-studio.pages.dev/?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=model_sunset&lt;/a&gt;&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>openai</category>
      <category>automation</category>
      <category>ai</category>
    </item>
    <item>
      <title>Singapore local service businesses: where website enquiries leak (2026 scan)</title>
      <dc:creator>Paopao Studio</dc:creator>
      <pubDate>Sat, 31 Oct 2026 01:39:24 +0000</pubDate>
      <link>https://dev.to/paopaostudio/singapore-local-service-businesses-where-website-enquiries-leak-2026-scan-4j6o</link>
      <guid>https://dev.to/paopaostudio/singapore-local-service-businesses-where-website-enquiries-leak-2026-scan-4j6o</guid>
      <description>&lt;p&gt;On 31 October 2026 we scanned &lt;strong&gt;183 Singapore local service business websites&lt;/strong&gt; from the outside: aircon, cleaning, moving, dental, beauty, physio, plumbing, electrical and renovation. For each site we read public DNS and fetched the homepage once. We submitted no forms and sent no email.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;convenience sample&lt;/strong&gt;. The sites were taken from public "best of Singapore" lists, so it does not represent all Singapore businesses. No business is named.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email authentication (N = 183 domains)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;155/183 (84.7%)&lt;/strong&gt; have no enforced DMARC policy: 79/183 (43.2%) have no DMARC record and 76/183 (41.5%) use &lt;code&gt;p=none&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;21/183 (11.5%) use &lt;code&gt;p=quarantine&lt;/code&gt; and 7/183 (3.8%) use &lt;code&gt;p=reject&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;30/183 (16.4%)&lt;/strong&gt; have no SPF record. 117/183 (63.9%) end SPF with &lt;code&gt;~all&lt;/code&gt; or &lt;code&gt;?all&lt;/code&gt;, and 1/183 publishes two SPF records.&lt;/li&gt;
&lt;li&gt;169/183 (92.3%) publish MX records. Of those, 142/169 (84.0%) have no enforced DMARC, and 15/169 (8.9%) have neither SPF nor DMARC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Missing DMARC is a &lt;strong&gt;risk, not a confirmed fault&lt;/strong&gt;. It makes spoofing easier and spam filtering more likely. It does not prove that any mail is being lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Homepage and forms (N = 170 readable homepages)
&lt;/h2&gt;

&lt;p&gt;13 homepages returned an error or a bot-challenge page, so these numbers use the 170 that returned readable HTML.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;178/183 (97.3%) served the homepage over valid HTTPS without an error. 5/183 (2.7%) returned a 5xx error on our single request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;88/170 (51.8%)&lt;/strong&gt; have a form on the homepage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;62/170 (36.5%)&lt;/strong&gt; have neither a form nor a &lt;code&gt;mailto:&lt;/code&gt; link on the homepage. 99/170 (58.2%) link to WhatsApp.&lt;/li&gt;
&lt;li&gt;0/88 homepage forms post to a host that doesn't resolve. 3/88 post to another host, and all of those hosts resolve.&lt;/li&gt;
&lt;li&gt;75/88 (85.2%) of sites with a homepage form have no enforced DMARC.&lt;/li&gt;
&lt;li&gt;Median time to first byte was 1.24 s (p75 2.13 s). That's one run from a US server, so treat it as rough.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The scan is passive, so it can't show whether any form actually delivers enquiries.&lt;/li&gt;
&lt;li&gt;Only homepages were checked. Forms on contact pages, or forms drawn by JavaScript, were missed.&lt;/li&gt;
&lt;li&gt;Timings come from a single run and will vary.&lt;/li&gt;
&lt;li&gt;The sample leans toward moving, cleaning and aircon businesses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Self-check for owners
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Submit your own form from a phone on mobile data. Does the notification arrive, and is it in spam?&lt;/li&gt;
&lt;li&gt;Look up your domain's SPF and DMARC records. You should have exactly one SPF record. Has DMARC sat at &lt;code&gt;p=none&lt;/code&gt; for months?&lt;/li&gt;
&lt;li&gt;Check that form notifications go to an inbox someone still reads.&lt;/li&gt;
&lt;li&gt;Tap your WhatsApp and phone links and check they open the right number.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full method, every metric as x/N, and the CSV column behind each number are on the &lt;a href="https://paopao-studio.pages.dev/sg-lead-leak-2026/?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=sg_report" rel="noopener noreferrer"&gt;report page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want the whole path traced, the &lt;a href="https://payhip.com/b/jW04s?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=lead_leak" rel="noopener noreferrer"&gt;Lead Leak Check ($197)&lt;/a&gt; maps it from the form to the first human reply. A &lt;a href="https://payhip.com/b/qgiD0?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=lead_leak" rel="noopener noreferrer"&gt;Starter build ($497)&lt;/a&gt; sets up one production workflow.&lt;/p&gt;

</description>
      <category>email</category>
      <category>dmarc</category>
      <category>webdev</category>
      <category>smallbusiness</category>
    </item>
    <item>
      <title>Find companies that just raised money, straight from SEC Form D filings</title>
      <dc:creator>Paopao Studio</dc:creator>
      <pubDate>Sat, 31 Oct 2026 01:13:16 +0000</pubDate>
      <link>https://dev.to/paopaostudio/find-companies-that-just-raised-money-straight-from-sec-form-d-filings-14l2</link>
      <guid>https://dev.to/paopaostudio/find-companies-that-just-raised-money-straight-from-sec-form-d-filings-14l2</guid>
      <description>&lt;p&gt;When a startup raises a round, its press release is optional. Its SEC filing usually is not. A US company that sells securities under Regulation D (most seed, Series A/B, SAFE and convertible-note rounds) has to file a &lt;strong&gt;Form D&lt;/strong&gt; with the SEC within 15 days of the first sale. Those filings are public on EDGAR, the same day they are disseminated.&lt;/p&gt;

&lt;p&gt;That makes Form D one of the cheapest "who just got budget" signals available for B2B sales, recruiting, and deal-flow research. The catch is that EDGAR gives you a daily index and an XML file per filing, mixed in with funds, SPVs and real-estate vehicles.&lt;/p&gt;

&lt;p&gt;This post shows how to get a clean, filtered list with an Apify Actor I maintain, &lt;a href="https://apify.com/goldenrod_serrano/sec-form-d-funding-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=find-newly-funded-companies-sec-form-d" rel="noopener noreferrer"&gt;SEC Form D Funding Tracker&lt;/a&gt; (disclosure: I built it). All output below is from real runs on 2026-10-31 (JST), covering filings from 2026-10-28 to 2026-10-30.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: free sample
&lt;/h2&gt;

&lt;p&gt;Switch on &lt;strong&gt;Free sample mode&lt;/strong&gt; (&lt;code&gt;"sampleMode": true&lt;/code&gt;). It returns 5 filings from operating companies in the last 3 days, ignores your filters, and is not charged. One row, trimmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Faex Technologies Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"form_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"D"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"filed_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"date_of_first_sale"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-14"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total_amount_sold_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2500000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"total_offering_amount_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4500000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"stage_hint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"seed ($1-5M)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"securities_offered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"equity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"option to acquire"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"investors_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"industry_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"issuer_city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LAFAYETTE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"issuer_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"year_of_inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"related_persons_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"operating_company"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"filing_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.sec.gov/Archives/edgar/data/2148280/000214828026000003/0002148280-26-000003-index.htm"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Form D lists executives and directors by name and address. The Actor drops those and keeps only counts (&lt;code&gt;related_persons_count&lt;/code&gt;, &lt;code&gt;related_person_roles&lt;/code&gt;), so the output is company-level data. &lt;code&gt;stage_hint&lt;/code&gt; is an amount-based guess, not an SEC field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: a filtered, scored run
&lt;/h2&gt;

&lt;p&gt;Tech and health companies that raised at least $500k in the last 3 days, with scoring and change tracking on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"daysBack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"operating_company"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"industries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Other Technology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Computers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Biotechnology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other Health Care"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minAmountSold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signalScoring"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"changeTracking"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stateKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"devto-demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestsPerSecond"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The run summary (&lt;code&gt;RUN_SUMMARY&lt;/code&gt; in the key-value store):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"days_requested"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_with_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"index_rows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;315&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"after_prefilter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"xml_fetched"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"xml_failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"matched"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"skipped_by_max_results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"is_baseline_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"new_issuer_rows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pushed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two business days of index, 315 Form D rows, 167 left after the cheap pre-filter, 80 filings checked in full, 5 returned because I set &lt;code&gt;maxResults: 5&lt;/code&gt;. &lt;code&gt;skipped_by_max_results: 87&lt;/code&gt; is the number of candidate filings the run skipped once the output was full, so they were not checked against the filters. With change tracking on, those 87 are still saved as seen and will not show up later, so for a real baseline raise &lt;code&gt;maxResults&lt;/code&gt; on the first run.&lt;/p&gt;

&lt;p&gt;The top two rows by score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stardust Semiconductors Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"filed_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"date_of_first_sale"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_first_sale_to_filing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"total_amount_sold_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2700000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"stage_hint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"seed ($1-5M)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"investors_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"industry_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other Technology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"year_of_inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_first_edgar_filing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"signal_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"score_reasons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+20 first filing: this is the issuer's first EDGAR filing (new to SEC filings)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+17 amount: $2,700,000 sold so far (log scale: $100k = 0, $100M+ = 35)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+15 young company: incorporated in 2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+15 industry: Other Technology (technology)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+10 freshness: filed 13 days after the first sale"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+3 traction: 100% of the offering sold, 2 investors"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Swep Bio, Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"issuer_city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SCARSDALE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"issuer_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"filed_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_first_sale_to_filing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"total_amount_sold_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2499989.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"industry_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Biotechnology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"year_of_inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_first_edgar_filing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hot"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And one that ranked lower, with the reason visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bluesonde Technologies, Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total_amount_sold_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1000000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"date_of_first_sale"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_first_sale_to_filing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;352&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"signal_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"warm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"score_reasons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+1 freshness: filed 352 days after the first sale"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The score adds six capped parts: amount raised (35, log scale), first EDGAR filing (20), incorporated within 5 years (15), industry (15), days from first sale to filing (10), and round progress / investor count (5). It helps you decide what to look at first. It does not predict anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: schedule it
&lt;/h2&gt;

&lt;p&gt;Keep the same &lt;code&gt;stateKey&lt;/code&gt; and schedule the Actor daily. Later runs only push filings you haven't received:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;change_type: "new"&lt;/code&gt;: an issuer you've never seen under this key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;change_type: "changed"&lt;/code&gt;: a new Form D or a &lt;strong&gt;D/A amendment&lt;/strong&gt; from an issuer you already have, with &lt;code&gt;previous_amount_sold_usd&lt;/code&gt; and &lt;code&gt;amount_sold_delta_usd&lt;/code&gt; (how much more they raised since the filing you saw)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Form D has no "closed" event, so there are no closed rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with the list
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;B2B sales:&lt;/strong&gt; a company that just closed a round has new budget and usually a hiring plan. Filter by industry, state and amount to match your ICP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recruiting / staffing BD:&lt;/strong&gt; freshly funded startups hire next. Pair it with a job-board monitor to see who raised &lt;em&gt;and&lt;/em&gt; opened roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VC / analysts:&lt;/strong&gt; spot rounds that were never announced, with security type (equity, SAFE, debt) and investor count.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limits worth knowing: only Reg D offerings that actually file a Form D appear; there are no investor names or valuations (Form D doesn't have them); &lt;code&gt;industry_group&lt;/code&gt; is the issuer's own choice and many pick "Other"; EDGAR publishes the daily index on business-day evenings (US Eastern).&lt;/p&gt;

&lt;h2&gt;
  
  
  Data source and pricing
&lt;/h2&gt;

&lt;p&gt;The Actor reads only SEC's public &lt;code&gt;/Archives/&lt;/code&gt; paths (the daily form index and each filing's &lt;code&gt;primary_doc.xml&lt;/code&gt;), sends a declared User-Agent with a contact email, and stays under SEC's fair-access rate limit (5 requests/second by default, I used 2 here).&lt;/p&gt;

&lt;p&gt;Pricing is pay per event: &lt;strong&gt;$0.008 per filing returned&lt;/strong&gt; ($8 per 1,000). No start fee. Sample mode, filtered-out filings and errors are free, and change tracking never charges twice for the same filing. The scored run above would have cost 5 × $0.008 = $0.04.&lt;/p&gt;

&lt;p&gt;Try it on the Apify Store: &lt;a href="https://apify.com/goldenrod_serrano/sec-form-d-funding-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=find-newly-funded-companies-sec-form-d" rel="noopener noreferrer"&gt;SEC Form D Funding Tracker&lt;/a&gt;. Source: &lt;a href="https://github.com/paopao-studio-ai/sec-form-d-funding-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=find-newly-funded-companies-sec-form-d" rel="noopener noreferrer"&gt;paopao-studio-ai/sec-form-d-funding-signals&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>apify</category>
      <category>sec</category>
      <category>startup</category>
      <category>sales</category>
    </item>
    <item>
      <title>Track hiring changes at target companies on Greenhouse, Lever and Ashby (with a hiring signal score)</title>
      <dc:creator>Paopao Studio</dc:creator>
      <pubDate>Sat, 31 Oct 2026 01:12:45 +0000</pubDate>
      <link>https://dev.to/paopaostudio/track-hiring-changes-at-target-companies-on-greenhouse-lever-and-ashby-with-a-hiring-signal-score-3agn</link>
      <guid>https://dev.to/paopaostudio/track-hiring-changes-at-target-companies-on-greenhouse-lever-and-ashby-with-a-hiring-signal-score-3agn</guid>
      <description>&lt;p&gt;If you sell to companies or place candidates with them, one of the most useful public signals is the company's own job board. A team that opens five Account Executive roles this month is building a sales org. A board that suddenly closes forty roles is telling you something too.&lt;/p&gt;

&lt;p&gt;Most of that data is public. Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee all publish job-board endpoints so that companies can show their openings on their own careers pages. The hard parts are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;normalizing six different formats,&lt;/li&gt;
&lt;li&gt;remembering what you saw last time, so you only look at what changed, and&lt;/li&gt;
&lt;li&gt;turning a pile of rows into "which account should I call first".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post walks through doing that with an Apify Actor I maintain, &lt;a href="https://apify.com/goldenrod_serrano/ats-hiring-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=monitor-greenhouse-lever-hiring-changes" rel="noopener noreferrer"&gt;ATS Jobs Monitor&lt;/a&gt; (disclosure: I built it). Everything below is copied from two real runs on 2026-10-31 (JST). Nothing is edited except trimming fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  The input
&lt;/h2&gt;

&lt;p&gt;Three target accounts on three different ATS, only sales roles, and both optional features switched on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"companies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"greenhouse:anthropic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lever:palantir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ashby:ramp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"account executive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"changeTracking"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stateKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"devto-demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signalScoring"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxJobsPerCompany"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputCompanySummary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;greenhouse:anthropic&lt;/code&gt; style inputs are exact. You can also paste a board URL (&lt;code&gt;jobs.lever.co/palantir&lt;/code&gt;) or a careers page, or a bare slug (&lt;code&gt;ramp&lt;/code&gt;), in which case the Actor tries all six ATS and marks the row &lt;code&gt;match_confidence: "guessed"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;changeTracking&lt;/code&gt; + &lt;code&gt;stateKey&lt;/code&gt; stores what was seen under that key, so the next run with the same key only outputs new, changed and closed jobs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signalScoring&lt;/code&gt; adds &lt;code&gt;signal_score&lt;/code&gt;, &lt;code&gt;signal_tier&lt;/code&gt; and plain-English &lt;code&gt;score_reasons&lt;/code&gt; to each company summary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxJobsPerCompany: 3&lt;/code&gt; only limits how many job rows this run &lt;strong&gt;outputs&lt;/strong&gt;. I used it to keep the demo short. With change tracking on, every scanned job is still saved as seen, so if you want the full list as your baseline, set it to &lt;code&gt;0&lt;/code&gt; on the first run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Run 1: the baseline
&lt;/h2&gt;

&lt;p&gt;The run took a few seconds and pushed 7 job rows plus 3 company summaries (one per company). Here are two job rows (trimmed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"job"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ramp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Senior Manager, Account Executive | Mid-Market"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"seniority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"manager"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New York, NY (HQ)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"work_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hybrid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"posted_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-10T00:03:38.552000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_long_open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"ats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ashby"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://jobs.ashbyhq.com/ramp/60ed4fac-3833-4495-9b0f-75e6dfe4b36c"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"job"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"change_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"palantir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"seniority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New York, NY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"work_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hybrid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"posted_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-01-09T15:50:00.613000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days_open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;294&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"is_long_open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"ats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lever"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://jobs.lever.co/palantir/24060586-7ba8-47c0-bfc1-f1dd5b82d8bd"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;seniority&lt;/code&gt; is a rule on the job title (not AI), and &lt;code&gt;is_long_open&lt;/code&gt; flags roles open for at least &lt;code&gt;longOpenDays&lt;/code&gt; days (30 by default). For recruiter BD, long-open roles are often the easiest conversation: the company is already struggling to fill them.&lt;/p&gt;

&lt;p&gt;The more interesting part is the company summary. This is Ramp's, trimmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"company_summary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"company_slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ramp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total_open_jobs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"posted_last_7_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"posted_last_30_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"remote_share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"top_departments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Engineering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"People &amp;amp; Talent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marketing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Compliance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"is_baseline_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"signal_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"score_reasons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+25 new demand: 48 roles posted in the last 30 days (13 in the last 7)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+15 seniority: 50 manager/director/executive roles (29%), 47% senior-or-above"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+15 department: biggest build-out is sales (77 of 171 roles)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+10 hard-to-fill: 125 roles open 30+ days (73%)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+9 velocity: 13 postings this week vs 11.2/week 30-day average (1.2x pace)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+8 volume: 171 open roles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"+5 remote: 89% of roles are remote"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same run scored Anthropic 81 (hot) and Palantir 57 (warm). Palantir's reasons show why it ranked lower:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+19 new demand: 17 roles posted in the last 30 days (2 in the last 7)
+0 velocity: 2 postings this week vs 4.0/week 30-day average (0.5x pace)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The score is the sum of seven capped parts: recent new roles (25), velocity (20), seniority (15), function (15), long-open roles (10), volume (10) and remote share (5). Every point comes with a reason, so you can disagree with it. It is a way to sort a list, not a prediction. If you sell to engineering teams rather than sales teams, pass &lt;code&gt;scoreFunctions&lt;/code&gt; so the function points go to the departments you care about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run 2: only what changed
&lt;/h2&gt;

&lt;p&gt;I ran the exact same input again right after the first run. The dataset came back with 3 rows, one company summary per company, and no job rows. Ramp's, trimmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"company_summary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"company_slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ramp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total_open_jobs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"new_jobs_since_last_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"changed_jobs_since_last_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"closed_jobs_since_last_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"net_change_since_last_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"is_baseline_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"signal_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hot"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the point: nothing changed, so there were no job rows to read and none to pay for. On a daily schedule, a later run outputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;change_type: "new"&lt;/code&gt; for roles that weren't there before,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;change_type: "changed"&lt;/code&gt; when a tracked field such as title or location changed,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;job_closed&lt;/code&gt; rows for roles that disappeared (filled or pulled). Closed rows are free.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a scan is incomplete (for example, a board was truncated), the Actor merges into the old state and does not report closures, so you don't get fake "closed" alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it for sales or recruiter BD
&lt;/h2&gt;

&lt;p&gt;A setup that works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put 50 to 500 target accounts in &lt;code&gt;companies&lt;/code&gt; (use &lt;code&gt;ats:slug&lt;/code&gt; or the board URL for accounts that matter, so a bare slug can't match the wrong company).&lt;/li&gt;
&lt;li&gt;Run once with &lt;code&gt;maxJobsPerCompany: 0&lt;/code&gt; as the baseline.&lt;/li&gt;
&lt;li&gt;Schedule it daily or weekly with the same &lt;code&gt;stateKey&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Send the dataset to Slack, Google Sheets, n8n, Make or Zapier through Apify integrations.&lt;/li&gt;
&lt;li&gt;Each morning, sort company summaries by &lt;code&gt;signal_score&lt;/code&gt; and read &lt;code&gt;score_reasons&lt;/code&gt;. Use the new job rows (titles and departments) as the opening line for outreach.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Things it does not do: it has no contact data or email addresses, it only covers companies on those six ATS (for Workday sites there is a separate &lt;a href="https://apify.com/goldenrod_serrano/workday-hiring-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=monitor-greenhouse-lever-hiring-changes" rel="noopener noreferrer"&gt;Workday Jobs Monitor&lt;/a&gt;), and it reads only public job postings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Pay per event on Apify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$0.001 per job row ($1 per 1,000 jobs)&lt;/li&gt;
&lt;li&gt;$0.005 per company summary&lt;/li&gt;
&lt;li&gt;a $0.00005 Actor start event&lt;/li&gt;
&lt;li&gt;closed-job rows and error rows are free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two demo runs above would have been 7 job rows + 6 summaries ≈ $0.04 in total. A daily run over 100 accounts where nothing changed costs mostly the summaries (100 × $0.005 = $0.50); switch &lt;code&gt;outputCompanySummary&lt;/code&gt; off if you only want changed jobs.&lt;/p&gt;

&lt;p&gt;Try it on the Apify Store: &lt;a href="https://apify.com/goldenrod_serrano/ats-hiring-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=monitor-greenhouse-lever-hiring-changes" rel="noopener noreferrer"&gt;ATS Jobs Monitor&lt;/a&gt;. The source is on GitHub: &lt;a href="https://github.com/paopao-studio-ai/ats-hiring-signals?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=monitor-greenhouse-lever-hiring-changes" rel="noopener noreferrer"&gt;paopao-studio-ai/ats-hiring-signals&lt;/a&gt;. Questions and bug reports are welcome there.&lt;/p&gt;

</description>
      <category>apify</category>
      <category>webscraping</category>
      <category>sales</category>
      <category>recruiting</category>
    </item>
    <item>
      <title>Ghost Workflow Medium: a 1B Gemma on a CPU summons dead cron jobs and reincarnates them as n8n workflows</title>
      <dc:creator>Paopao Studio</dc:creator>
      <pubDate>Fri, 30 Oct 2026 02:16:39 +0000</pubDate>
      <link>https://dev.to/paopaostudio/ghost-workflow-medium-a-1b-gemma-on-a-cpu-summons-dead-cron-jobs-and-reincarnates-them-as-n8n-3i37</link>
      <guid>https://dev.to/paopaostudio/ghost-workflow-medium-a-1b-gemma-on-a-cpu-summons-dead-cron-jobs-and-reincarnates-them-as-n8n-3i37</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Every small business has ghosts in its machines: a crontab line nobody remembers writing, a Python 2 report that "just works" every Monday at 8, a disk alert that pings a chat room nobody reads. When the person who wrote them leaves, the knowledge dies with them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ghost Workflow Medium&lt;/strong&gt; is a tiny, fully offline sÃ©ance for those ghosts. You hand it the remains of an old script. A local &lt;strong&gt;Gemma 3&lt;/strong&gt; model running in &lt;strong&gt;Ollama&lt;/strong&gt; speaks &lt;em&gt;as the ghost&lt;/em&gt; and tells you in three sentences what it did in life. Then it reincarnates the script as an &lt;strong&gt;n8n workflow JSON&lt;/strong&gt; you can import.&lt;/p&gt;

&lt;p&gt;It's my DÃ­a de los Muertos ofrenda for the scripts that quietly kept small shops running for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7plbtwcvtres13su5qig.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7plbtwcvtres13su5qig.gif" alt="Real terminal run: gemma3:1b on an 8-core CPU, no GPU" width="599" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The GIF is rendered directly from the raw run log in the repo (&lt;code&gt;logs/run_20261029T143407Z_gemma3-1b.log&lt;/code&gt;). No face, no edits.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first ghost is a 2009-style backup script: &lt;code&gt;mysqldump&lt;/code&gt;, &lt;code&gt;tar&lt;/code&gt;, &lt;code&gt;scp&lt;/code&gt; to a NAS, &lt;code&gt;find -delete&lt;/code&gt;, then &lt;code&gt;mail&lt;/code&gt; to the boss, every night at &lt;code&gt;0 3 * * *&lt;/code&gt;. Here is the real output from &lt;strong&gt;gemma3:1b&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ðŸ•¯  Summoning the ghost of backup_cron_2009.sh with gemma3:1b ...
ðŸ‘» Alright, let's seeâ€¦ I was the keeper of this little business, a silent observer, and my every action was vital. I meticulously copied the shop's data, ensuring everything was safe, and then meticulously archived it, safeguarding the business's future. Without me, the shop would cease to exist, and the records would vanish into the digital void. It's a chilling thought, really, that my existence is inextricably linked to its survival.
   (confession: 97 tokens, 3.9s)
   (plan attempt 1: 149 tokens, 9.1s)
   ðŸ§¿ exorcised step 'Send Notification': http://192.168.1.20:12345/status.html is not in the original script
âœ¨ Reincarnated -&amp;gt; reborn/backup_cron_2009.json (3 nodes: scheduleTrigger -&amp;gt; executeCommand -&amp;gt; emailSend); structure check passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The same ghost summoned with &lt;strong&gt;gemma3:4b&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ðŸ‘» I awoke each morning precisely at 3:00 AM, initiating the relentless cycle of database backups and file archives. The shop owner and his assistant relied on my execution to safeguard their inventory and customer records, a silent, digital tether to their daily operations. Should I be erased, the meticulously crafted backups would vanish, plunging the shop into an immediate, irreversible chaos of lost data and fractured invoices.
   (confession: 81 tokens, 23.0s)
   (plan attempt 1: 277 tokens, 41.4s)
   ðŸ”§ re-typed step 'Copy to NAS' as a shell command (no URL in it)
âœ¨ Reincarnated -&amp;gt; reborn_gemma3-4b/backup_cron_2009.json (6 nodes: scheduleTrigger -&amp;gt; executeCommand -&amp;gt; executeCommand -&amp;gt; executeCommand -&amp;gt; executeCommand -&amp;gt; emailSend); structure check passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I imported the results into a local n8n 2.45.6 with the n8n CLI (&lt;code&gt;Successfully imported 1 workflow.&lt;/code&gt; Ã—3 per model) and opened them in the editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwhq70p6d9pkvrgztk7o5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwhq70p6d9pkvrgztk7o5.png" alt="The reincarnated backup workflow in the n8n editor" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fau3gkgools3dshhjhueb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fau3gkgools3dshhjhueb.png" alt="The reincarnated disk alert workflow: schedule, df, code, HTTP POST" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/paopao-studio-ai" rel="noopener noreferrer"&gt;
        paopao-studio-ai
      &lt;/a&gt; / &lt;a href="https://github.com/paopao-studio-ai/ghost-workflow-medium" rel="noopener noreferrer"&gt;
        ghost-workflow-medium
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local Gemma reads old cron/bash scripts and reincarnates them as validated n8n workflow drafts
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;👻 Ghost Workflow Medium&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A local, offline séance for dead scripts.&lt;/strong&gt; Feed it an old cron job, bash script or Python 2 report. A small open-weight &lt;strong&gt;Gemma 3&lt;/strong&gt; model running in &lt;strong&gt;Ollama&lt;/strong&gt; speaks &lt;em&gt;as the ghost&lt;/em&gt; and says what the script did in life. Then the tool reincarnates the script as an &lt;strong&gt;n8n workflow JSON&lt;/strong&gt; that you can import.&lt;/p&gt;

&lt;p&gt;Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 4: &lt;em&gt;Ghost in the Machine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/paopao-studio-ai/ghost-workflow-medium/docs/demo_gemma3-1b.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpaopao-studio-ai%2Fghost-workflow-medium%2FHEAD%2Fdocs%2Fdemo_gemma3-1b.gif" alt="terminal demo (real run, gemma3:1b on CPU)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Every small business has ghosts in its machines: a crontab line nobody remembers writing, or a weekly report that "just works". When the person who wrote it leaves, the knowledge goes with them. These scripts often contain internal hostnames, paths and email addresses, so you may not want to paste them into a cloud model. Everything here runs on one CPU-only machine, with no API keys and no network calls except to &lt;code&gt;localhost:11434&lt;/code&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How&lt;/h2&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/paopao-studio-ai/ghost-workflow-medium" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;MIT-licensed. The Python code is ~400 lines and stdlib-only. The repo includes the three sample ghosts, the reborn outputs from both models, and every raw log.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Model:&lt;/strong&gt; Gemma 3, via Ollama, 100% local on an 8-core CPU with no GPU. The default is &lt;strong&gt;gemma3:1b&lt;/strong&gt;, the smallest Gemma 3 (~800 MB download); &lt;strong&gt;gemma3:4b&lt;/strong&gt; is optional. There are no API keys, and the only network call goes to &lt;code&gt;localhost:11434&lt;/code&gt;. That matters because old scripts are full of internal hostnames, paths and email addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 1: don't ask a 1B model to write n8n JSON.&lt;/strong&gt; A real n8n workflow has node type strings, versioned parameters, positions and a connections map keyed by node name. A 1B model can't produce that reliably. So Gemma does two smaller jobs instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Confess&lt;/strong&gt; (temperature 0.7): speak as the script, in three sentences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; (structured output): Ollama's &lt;code&gt;format&lt;/code&gt; parameter takes a JSON schema, so Gemma can only answer with &lt;code&gt;{workflow_name, trigger: {type, cron}, steps: [{kind, name, detail}]}&lt;/code&gt;, with 1â€“6 steps of kind &lt;code&gt;command | http | email | code | readFile | writeFile&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A ~100-line &lt;strong&gt;deterministic compiler&lt;/strong&gt; then turns the plan into real n8n nodes: &lt;code&gt;scheduleTrigger&lt;/code&gt; with a cron expression, &lt;code&gt;executeCommand&lt;/code&gt;, &lt;code&gt;httpRequest&lt;/code&gt;, &lt;code&gt;emailSend&lt;/code&gt;, &lt;code&gt;readWriteFile&lt;/code&gt; and &lt;code&gt;code&lt;/code&gt;. It also adds stable UUIDs, positions and a linear connection chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2: small models hallucinate, so check their work against the source.&lt;/strong&gt; Gemma 1B's mistakes were very consistent, so I added guardrails that don't use the LLM at all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ðŸ§¿ Exorcism (grounding):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Any step whose URL or email address doesn't appear in the original script gets removed.&lt;/li&gt;
&lt;li&gt;In my final run, gemma3:1b invented a "Send Notification" step for the backup script, calling &lt;code&gt;http://192.168.1.20:12345/status.html&lt;/code&gt;. The script only &lt;code&gt;scp&lt;/code&gt;s to that NAS address; there is no web endpoint and no port 12345. The step was removed.&lt;/li&gt;
&lt;li&gt;For the sales report, it copied &lt;code&gt;https://hooks.example.org/done&lt;/code&gt; straight from the few-shot example in my prompt. That step was removed too.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ðŸ”§ Repair:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;In an early run, the model pasted the whole crontab line into the &lt;code&gt;cron&lt;/code&gt; field. Now the field is trimmed to the 5 schedule fields.&lt;/li&gt;
&lt;li&gt;An "http" step that's really &lt;code&gt;scp&lt;/code&gt; gets re-typed as a shell command.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;validate.py&lt;/code&gt; checks for exactly one trigger, at least one action, and unique names.&lt;/li&gt;
&lt;li&gt;It checks that every node type is known and the cron expression is valid.&lt;/li&gt;
&lt;li&gt;It checks that every connection points to a real node and every node is reachable from the trigger.&lt;/li&gt;
&lt;li&gt;If any check fails, the errors go back to Gemma for one retry.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Results (from the logs in the repo):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ghost&lt;/th&gt;
&lt;th&gt;gemma3:1b&lt;/th&gt;
&lt;th&gt;gemma3:4b&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;backup (cron &lt;code&gt;0 3 * * *&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;schedule â†’ mysqldump â†’ email&lt;/td&gt;
&lt;td&gt;schedule â†’ dump â†’ archive â†’ copy to NAS â†’ clean old backups â†’ email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;disk alert (&lt;code&gt;*/30 * * * *&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;schedule â†’ the curl call&lt;/td&gt;
&lt;td&gt;schedule â†’ df â†’ code â†’ HTTP POST to the real webhook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;weekly sales report (&lt;code&gt;0 8 * * 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;schedule â†’ command â†’ email&lt;/td&gt;
&lt;td&gt;schedule â†’ one big code node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;all 3 ghosts, wall time&lt;/td&gt;
&lt;td&gt;~34 s&lt;/td&gt;
&lt;td&gt;~2.5 min&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both models got every schedule right, and all six workflows passed validation and imported into n8n. 1B is fast and gives you a skeleton, but it drops steps: tar, scp and cleanup are missing from the backup. 4B gives you a real draft, though it embellishes the stories; the sales script's owner became a "Mr. Henderson" who isn't in the script. One n8n gotcha: recent versions disable the &lt;em&gt;Execute Command&lt;/em&gt; node by default, so it shows up as a "?" node. I had to start my local instance with &lt;code&gt;NODES_EXCLUDE="[]"&lt;/code&gt; to see the terminal icons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it is not:&lt;/strong&gt; a finished migration. The output is a scaffold. It has no credentials, its Code nodes carry &lt;code&gt;TODO&lt;/code&gt;s, and you should review every shell command before activating anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;I run a small automation studio that builds n8n workflows for small merchants and training schools. These clients can't send their internal scripts to a closed cloud model, and they can't afford enterprise migration consultants. Open-weight Gemma, open-source Ollama and n8n change that. A single developer can run the whole "AI migration" on an ordinary CPU, offline, with every step inspectable: the prompt, the plan, the guardrails, the final JSON. A 1B model wouldn't be trustworthy on its own. With the weights local and the checks open, I could see exactly where it hallucinated and fix it in code. That is the kind of control open models give you.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I built this with help from an AI coding assistant. It handled the installs, the scaffolding and the debugging loop of "run Gemma, read the log, add a guardrail". Every output in this post comes from real runs on my machine, and the raw logs are in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spirit of It
&lt;/h2&gt;

&lt;p&gt;An ofrenda remembers the dead so they are not forgotten. Old scripts deserve the same. Before you delete them, let them tell their story, then give them a new life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
