Building a Multi-Agent Workflow for Your Business
Back to Blog
AI Agents2025-10-22· 7 min read

Building a Multi-Agent Workflow for Your Business

Building a Multi-Agent Workflow for Your Business

#ai-agents#automation

I tried the single-agent approach first. One script that does everything — posts content, scans bounties, generates leads, monitors replies. It worked until it didn't. The script got too long, failures in one task cascaded into others, and debugging was a nightmare.

So I split it into specialized agents. Each one does one thing well, runs on its own schedule, and fails independently. Here's how I structured it and why it works better than a monolith.

The Agents

1. Social Poster Agent (brand_cron.py + social_poster.py)

Handles all social media posting across three brands. Fires on cron — 9 AM for BMX content, noon for Axon products. Uses ThreadPoolExecutor to post to Instagram, Pinterest, X, LinkedIn, Threads, and Facebook concurrently.

Each platform has its own posting function with platform-specific DOM handling. All browser-automated via Playwright + CDP. No platform APIs.

Schedule: Twice daily (per brand) + Pinterest every 2 hours Failure mode: If one platform fails, others continue. Errors logged to cron-errors.log.

2. Bounty Scanner (bounty_monitor.py)

Scans GitHub repos for open bounties. When it finds one: auto-claims, generates a GPT-4.1 proposal, delegates the fix to a coding agent, pings Telegram when the PR is ready.

Schedule: Every 5 minutes during SF peak hours (10-11 AM, 5-7 PM ET), every 15 minutes off-peak Failure mode: Logs to bounty-monitor.log, tracks seen bounties in seen-bounties.json to avoid duplicate claims

3. X Reply Monitor (x_reply_monitor.py)

Watches tech influencer tweets and auto-drafts contextual replies for @AxonModalAI and @billykennedybmx. Has a politics filter to skip anything off-brand. Recently switched from draft queue to auto-send.

Schedule: Every 30 minutes Failure mode: Drafts queue to x-reply-queue.json if auto-send fails

4. Lead Engine (lead_engine.py)

Scrapes business directories, researches contacts, scores them, adds to the master pool. Covers automotive, legal, and real estate verticals across NEPA and surrounding areas.

Schedule: Twice daily Failure mode: Logs to lead-engine.log, appends to master-leads.json

5. Image Generator (batch_image_gen.py)

Generates images in bulk — blog heroes, game assets, Pinterest pins. Runs style-isolated batches with cooldowns between them to prevent style bleed.

Schedule: On-demand (not cron — I trigger this when I need a batch) Failure mode: Logs each generation to image-gen-log.json, resumes from last successful image on restart

Why Separate Agents Beat a Monolith

Independent Failure

When bounty_monitor.py crashes, social posting keeps running. When Instagram's DOM changes and social_poster.py needs a fix, the lead engine doesn't care. Each agent is its own process with its own error handling.

In the monolith version, a timeout in the bounty scanner would block the social posting cron from firing. One bad API call could take down everything. Splitting them eliminated cascading failures entirely.

Independent Schedules

The bounty scanner needs to run every 5 minutes during peak hours. Social posting runs twice daily. The lead engine runs twice daily. The X reply monitor runs every 30 minutes.

In a monolith, you'd need complex internal scheduling logic. With separate agents, each one gets its own cron line. Simple, readable, independently adjustable.

Independent Logs

Each agent writes to its own log file: cron-axon.log, cron-bmx.log, bounty-monitor.log, lead-engine.log. When something breaks, I know exactly which file to check. No grepping through a unified log trying to find the relevant lines.

Independent State

Each agent manages its own state:

  • daily-axon-state.json — last Axon post timestamp and status
  • daily-bmx-state.json — last BMX post timestamp and status
  • seen-bounties.json — bounties already claimed
  • axon-post-state.json — product rotation queue position
  • x-reply-queue.json — pending reply drafts

State files are tiny JSON files on disk. No database, no shared state between agents. If one agent's state gets corrupted, the others are unaffected.

The Coordination Layer

The agents don't talk to each other directly. They coordinate through the filesystem:

  • The image generator writes images to a known directory
  • The social poster reads from that directory
  • The bounty monitor writes PR status to a JSON file
  • The memory consolidation process reads all logs and writes a daily summary

This is intentionally simple. No message queues, no pub/sub, no event buses. Files on disk. It works, it's debuggable, and it never goes down because there's no infrastructure to go down.

The Daily Memory File

Every day, the system produces a memory file (memory/2026-04-03.md) that consolidates everything:

  • What shipped (which platforms posted, which bounties claimed, how many leads generated)
  • What broke (which platforms failed, what errors occurred)
  • Architecture decisions made
  • Tomorrow's priorities

This is my single point of review. I read one file, get the full picture, and decide if anything needs attention. Most days, nothing does.

How to Structure Your Own Multi-Agent System

  1. One agent per concern. If it has its own schedule, its own failure mode, and its own state, it should be its own script.
  2. Cron for scheduling. Don't build a scheduler. Use the one your OS already has.
  3. Files for state. JSON files on disk. No database until you actually need one.
  4. Filesystem for coordination. Agents read and write to known directories. No message passing.
  5. Separate logs. One log file per agent. Errors in their own file.
  6. Daily summary. One file that tells you everything that happened. Read it once, move on.

The multi-agent architecture I use — including all the agents, the state management, and the coordination patterns — is available at axon.nepa-ai.com. Built from running this in production, not from a whiteboard.