Automation Pipeline3 min read

My Sleep App and My K-pop Quiz Were Wearing the Same Hashtags

My Instagram crosspost pipeline put the same default hashtags on every app. Nothing errored, because the pipeline only checked that tags were attached, never that they fit the app. This post covers generating tags once per app, caching them, keeping the defaults only as a fallback, and what I still don't know.

#instagram#hashtags#claude-cli#automation#caching
Left: different apps sharing one hashtag set. Right: separate generated and cached hashtag lists per app.
One default tag set shared by every app became per-app generated tags, with the default kept only as a fallback.

Every app wore the same default tags

My automated Instagram crosspost adds hashtags to the end of each caption. The question was where those hashtags came from. The caption code had exactly one default tag set, and every post got it no matter which app it was for.

Looked at app by app, that's awkward. A sleep app, a women's health app, and a K-pop song-guessing app all went out with identical hashtags. People interested in sleep and people looking for a K-pop quiz search for completely different words, yet every post was entering through the same door.

From the pipeline's side, nothing was wrong. Posts went up, captions had hashtags, no errors. If the check is whether hashtags are attached, it passes. Nobody checked whether these were hashtags the people looking for this app would actually use.

In your own auto-posting pipeline, what default gets attached to every piece of content, and have you ever checked who it actually reaches?

Each app needs different tags, but writing them by hand doesn't scale

With one app, you just write the tags yourself. With several, picking niche tags per app and per language becomes repetitive work, especially since this channel covers Korean, English, and Japanese.

There were three options: keep the defaults, hand-write a tag list per app, or generate tags from app metadata.

What would you do? Call an LLM on every post for fresh tags, or generate once per app and freeze the result?

Generate once per app, cache it, fall back to defaults

Here's the structure I chose.

  • insta_hashtags.py passes the app's name and hook line to the claude CLI.
  • claude returns 12 tags that mix ko/en/ja and combine niche and large tags.
  • The result is cached per app in insta_hashtags.json.
  • When insta_crosspost.py builds a caption, it uses that app's cached tags first and falls back to the old default set if none exist.

The reason for not calling on every post is simple: an app's character doesn't change from post to post. Calling every time costs money and time, and the same app would get different tags on each post. A file cache also means I can read the generated tags and edit them by hand.

Keeping the fallback was deliberate too. Posting shouldn't stop because one app has no cache entry. But this doesn't remove the original problem everywhere. It only removes it for apps where generation has run. In this commit, that's one sleep app, two women's health apps, and one K-pop song-guessing app. Every other app still goes out with the default tags.

Self-check

  • Do your automated posts pull hashtags, categories, or keywords from a single default, regardless of content?
  • Does your pipeline check only that something is attached, not that it fits?
  • When a fallback kicks in silently, can you tell which items went out on the fallback?

The honest part

There are no outcome numbers in this post. I hadn't measured whether reach or impressions changed after switching to per-app tags as of this commit, so I can't say it helped. I also didn't verify that claude's 12 picks have real search volume, or that the niche-to-large ratio is right. For now it's just a plausible-looking list from a model. The cache stays as written, so it won't refresh when trends shift. And as long as the fallback exists, any app I haven't run generation for keeps shipping with the same default tags it always had.

Related