smm-factory
An Instagram team of zero humans for about $0.40 a week — you approve in three taps.
For a founder — cost, outcome, time
- Cost
- $0.40/wk
- Posts
- 40
- Violations
- 0
- Approval
- 3 taps
Noble needed Instagram credibility to win barbershops. A specialist costs $2–3K a month, an agency $5K+, and founder-posting collapses by week two.
40 posts in two months at about $0.40 a week — with every taste call still human.
- Python
- Claude Opus 4.7
- Claude Sonnet 4.6
- Claude Haiku 4.5
- Playwright
- FFmpeg
- Supabase
- Slack Bolt
- Render.com
- GitHub Actions
smm-factory is a multi-agent SMM system that ran a barbershop-SaaS Instagram for 2 months on its own — 40 posts, 13 niche followers, zero moderator violations, ~$0.40/week in AI costs. Built as Noble's in-house marketing team, minus the team.
AI does everything except the taste calls. Three-tap Slack approval, ~1 hour of my time per week, forty posts shipped at ~$0.40/week in model costs.
Context
Noble is a booking SaaS for barbershops and independent salons — the kind of business that lives on Instagram but rarely has time for it. Solo owners already juggle staff, chairs, and no-shows. Marketing consistently falls off the table.
I built smm-factory as Noble's Instagram team: a system that plans a week of content, generates it, posts it, engages with the community, and reports back — end to end — with human approval only where it actually matters.
Problem
Noble had a chicken-and-egg: acquire barbershops on Instagram, but need Instagram credibility first. Doing it manually meant either a full-time SMM specialist ($2–3K/month), an agency ($5K+ and generic B2B templates), or founder-posting (a pattern that collapses in week two).
I wanted something that runs itself but where I stay the taste-maker. Not "AI writes everything" — "AI does everything except the taste calls."
Division of Labor
| Layer | Who does it |
|---|---|
| Strategy (ICP, pillars, voice) | Me → Claude Sonnet distills into per-client strategy in DB |
| Weekly content plan (7 posts) | Claude Opus (1×/week, cost amortized) |
| Captions, comments, hashtags | Claude Haiku (fast + cheap, high volume) |
| Media (reels, carousels, posts) | Playwright screenshots + FFmpeg + Pexels/Jamendo assets |
| Approval | Human, always — Slack cards, three buttons |
| Posting + engagement | Autonomous, gated by Orchestrator state machine |
| Learning | Analytics Agent (weekly) + Self-Improvement (monthly) → I approve, doesn't auto-apply |
Model stratification wasn't premature optimization. First month running Opus for everything ≈ $8/day. After stratification: ~$0.30–0.50/client/week. Same output quality where it matters, 20× cheaper.
Two loops · one Slack approval each
Weekly content pipeline — Opus plans, Haiku writes, I tap
Mon 09:00 Kyiv · 1×/week
- Data / signal
- Process step
- Decision / gate
- Outcome
- Flow
- Key path / outcome
- Async / optional
Read as steps (5)
- 01Strategy → Weekly plan
- 02Weekly plan → Generate
- 03Generate → Slack approval
- 04Slack approval → Post to IG (✓ approved) — approve
- 05Slack approval → Revise — edit (async / optional)
Learning loop — analytics proposes, I decide, nothing auto-applies
weekly + monthly cadence
- Data / signal
- Process step
- Decision / gate
- Outcome
- Flow
- Key path / outcome
- Async / optional
Read as steps (5)
- 01Analytics → Self-Improvement
- 02Self-Improvement → Strategy v+1
- 03Strategy v+1 → I approve
- 04I approve → Promote (✓ approved) — approve
- 05I approve → Discard — ignore (async / optional)
Prompt Architecture
The system's superpower is the knowledge/ directory — 12 markdown files (00_overview through 11_orchestrator) covering the 8 agents, 3 shared systems (content pipeline, approval manager, database schema), and the orchestrator. One rule I set for myself: Rules = Code. If a rule lives only in markdown, it doesn't exist. Every markdown rule must be in code.
That flipped every Claude session from "here's a codebase, please read it all" into "here's the spec and the one file we're touching." Sessions got sharp.
Agent replay · Mon 09:00 — one weekly content cycle
Step through one weekly cycle. Arrow keys ← → or the buttons below.
Cron fires
09:00:00Mon 09:00 Europe/Kyiv — orchestrator wakes. Reads 11_orchestrator.md to decide which agent runs first this week.
Every folder in agents/ has a matching file in knowledge/. When the two drift, the knowledge file is the bug — code is ground truth, markdown is the spec that must agree with it.
The engagement agent — where the system actually touches humans
Content generation is the showy part. The engagement agent is the one that moves the needle on a booking SaaS, because it runs while the owner is cutting hair. Two behaviors, both on cron, both bypassing me entirely:
- Comments on target feeds. A daily batch picks in-niche posts (own-niche hashtags from
trends, competitor accounts flagged in strategy). Haiku writes one conversational line per post — matched to context, no CTA, no emoji spam. The orchestrator rate-limits by account so the pattern reads organic, not scripted. - Replies to DMs. Incoming DM triggers the agent inline: Haiku reads it, classifies against response templates in
06_engagement_agent.md, drafts, sends. No Slack-approval on this hop — the whole point of the engagement loop is closing the conversation before the lead cools.
The path I wanted and couldn't take. The clean version is Instagram Graph API through Meta Business Suite — official endpoints for instagram_manage_comments and instagram_manage_messages. App Review for those write-scopes requires passing Business Verification first: a registered legal entity, business documents on file, DUNS or local equivalent, a reviewed privacy policy on an active production domain. I was running this as a solo pilot — no incorporated company behind it, no fast path to one that didn't bulldoze the point of the pilot. Meta's gate doesn't bend for individuals, by design, and there's no sandbox-mode escape hatch for write scopes.
So the fallback is a Playwright session driven by a long-lived IG cookie, same mechanic the publisher uses to post. It's fragile — cookies rotate, flows break on IG UI updates (the login_required in the log below is exactly this failure mode in the trends path) — it's not TOS-clean, and it won't scale past a handful of clients before IG's spam heuristics catch on. For a two-month pilot it was the only way to ship. The 0 IG violations in Results below reads differently once you know this: it's a function of staying slow and under rate-limit, not of the architecture being clean.
technical
00:21:01 [INFO] Generating content for 1 clients
00:21:01 [INFO] Starting content pipeline for Noble
00:21:04 [INFO] Generating week 2026-06-29 for 'Noble'
00:21:11 [INFO] Trends fetched for niche='barbershop booking SaaS' geo='US': 0 trending, 3 rising
00:21:16 [ERROR] Hashtag top medias failed for #barberlife: login_required
00:22:28 [INFO] Instagram trends collected: 0 hashtags, 0 audio tracks, 0 patterns
00:22:58 [INFO] POST https://api.anthropic.com/v1/messages → 200 OK
00:22:59 [INFO] POST https://cloud.leonardo.ai/api/rest/v1/generations → 200 OK
00:23:08 [INFO] Leonardo background generated: bg.jpg (324KB)
00:23:13 [INFO] Uploaded feed_post.png → r2.cloudflarestorage.com/clients/.../2026-06-29/day01/
00:23:14 [INFO] Day 1 (Monday) [feed_post] saved
00:29:18 [INFO] Day 2: bg_video=found (Pexels, portrait 2160×4096)
00:31:46 [INFO] Day 2: animation.mov ready
00:32:01 [INFO] Day 2: composite OK (2690 KB)
00:32:01 [INFO] Day 2: music → hustle.mp3
Real excerpt from logs/content_gen.log, 2026-06-23. Instagram trend hashtag calls fail with login_required (expected when the session cookie isn't refreshed) — the pipeline degrades to niche-only trend data, Anthropic still writes the week, Leonardo generates the backgrounds, R2 stores the renders, Supabase records the Day. Day 1 (feed post) in ~2 min; Day 2 (reel composite with Pexels bg + alpha animation + music) in ~11 min on GH Actions free tier.
Iteration Moment — a decision I unwound in 21 minutes
Integrated Playwright + FFmpeg for reel rendering. First working commit. Used Playwright's native page.video(). Defensible on paper. In practice: animation timings weren't frame-aligned, jittery output, dropped frames.
Fix commit — switched to screenshot-per-frame at 30fps → FFmpeg compositing. Deterministic output every time. Slower to render, but rendering runs once on GitHub Actions free tier.
Ship, test, kill in 21 minutes.
What this taught me: with Claude, the useful skill isn't defending design-pass decisions — it's the speed to unwind them once reality argues back.
Trade-Offs I'd Explain to a Client
- No Meta Business API — cookie-session instead. The clean path for comments + DMs is Instagram Graph API. App Review for the write scopes requires passing Meta's Business Verification, which requires a registered legal entity — I was a solo pilot without a company. No fast way around the gate, by design. Fell back to a Playwright-driven IG session cookie. Fragile, outside TOS, shippable the same evening. The single biggest reason the system isn't production-ready without a corporate wrapper around it first.
- GitHub Actions as render farm instead of a GPU box. 5–15 min latency, offloaded to free tier. Would break past ~50 clients — good problem.
- Slack as the only UI. Every approval, status, insight — Slack. Custom dashboard would've cost weeks; Slack costs zero. Rate limits push me toward batching, which turned out to be a UX win.
- Self-Improvement never auto-applies. Monthly it writes a new strategy version, archives the old, posts summary in Slack. I approve or ignore. Costs me weekly attention. Prevents silent drift into whatever Claude currently thinks is right.
Results — 2-month pilot (2026-07 → 2026-08)
The honest read: 13 followers is small. This is a genuinely narrow audience (specific service tier, specific behavior). The pilot proved the system can run at cost. The open question it didn't resolve — and the reason this stayed a pilot rather than scaling into Noble's live marketing stack — was whether the creative ceiling of autonomous content was high enough for the same targeting to actually convert.
Reflection
"AI can now do everything" is technically true, operationally false. AI is a component; the system is what ships.
Model stratification is a UX decision, not just a cost one
Opus writing a comment reads as AI-trying-too-hard. Haiku writing a comment reads as human. Match model personality to task — 20× cheaper is the second-order win.
Human-in-the-loop only works if the loop is fast
Three-tap Slack approval = 2-minute weekly review. A dashboard would have died by month two.
Architecture is where the AI story actually gets told
State machines, safety valves, approval gates, version histories. Autonomous content is the output; the discipline that produces it is the deliverable.
Receipts
How it was made
Token scorecard
Pre-ShipLoop sessions ran in shared home-dir logs; token attribution isn’t reconstructable.
- Complexity
- M
- Duration
- 27 days
- Tier
- 0 · naked
Model mix
- Sonnet
- 90%
- Haiku
- 10%
Build timeline
85 days from Jun 8 to Aug 31, 38 commits
- Phases
- 3
- Days
- 85
- Peak day
- —
- Peak commits
- 11
Have a smm-factory-sized problem?
Send one paragraph about it. I reply within two business days with a scope and a fixed price.