← BB / INDEX
CASE STUDY·2026·LIVESOLO. ARCHITECTURE, ENGINEERING, OPS.

Presswork

Four AI agents that run an Etsy print-on-demand pipeline: trend discovery, artwork generation, listing, and margin tracking. They hand off through a shared Postgres schema, so each stage runs and is inspected on its own, and a person approves every listing before it goes live.

STACK

  • Python
  • TypeScript
  • Claude API
  • Supabase
  • fal.ai
  • Railway
Design agent review queue: AI-generated artwork with trend brief context
Design agent queue: trend brief to finished artwork, awaiting approval.

INTRO

Four agents that run an Etsy print-on-demand pipeline: trend discovery, artwork generation, listing, and margin tracking, with a human approving or rejecting each listing before it publishes.

It looks like plain orchestration until you build it. Image generation bills per call, a retried write against an order can count the same sale twice, and LLM output drifts in ways that aren't obvious up front. Four things in the system exist because of that: idempotency, dedup, rate limits, and margin math that has to reconcile a sale in the buyer's currency against fees and print costs quoted in another.

01

SECTION

Four agents, one schema, no orchestrator

The agents don't call each other. They read and write a shared Supabase schema, and each owns one stage of the pipeline. Scout writes `trend_briefs`. Design picks up briefs in `pending` status and writes `design_packages`. Listing picks up packages and publishes to Etsy. Ledger watches Etsy receipts and writes `orders` with derived margins. Status transitions on shared rows are the whole API.

There's no central orchestrator, so each agent has its own runtime, deployment cadence, and retry behavior. Scout runs on a nightly cron, since trends don't change minute to minute. Design and Listing poll every 15 minutes, because image generation is slow and expensive. Ledger polls every 30 minutes, because Etsy receipts settle slowly. They scale and fail on their own: if fal.ai is unavailable, Design stalls at its own stage while the others keep working through the existing backlog, because none of them is waiting on a call it doesn't make itself.

Presswork listings dashboard: an empty review queue reading inbox zero, above eight rows marked active at 24.99 dollars each, with back up to pending and clear controls
The Listings tab of the running app: eight rows marked active at $24.99, with the human review queue above them sitting at inbox zero.
02

SECTION

Polyglot on purpose

Scout and Design are Python, using `httpx`, `pydantic`, and `structlog`. Listing and Ledger are TypeScript, using `Zod` for schemas and `Bottleneck` for rate-limited Etsy calls. The shared schema is the contract that lets them differ. Each language has its own client library in the monorepo, `packages/shared_py` for the Python agents and `packages/shared` for TypeScript, wrapping Supabase access, Etsy auth refresh, and Slack and email notifications.

The split is deliberate: Python's data and AI tooling for the LLM-heavy upstream stages, and TypeScript's type safety and async ergonomics for the money-touching downstream ones. The cost is doing everything twice: two dependency trees, two client libraries that have to stay in step with one schema, and a CI job that typechecks both stacks and runs an end-to-end test driving a single trend brief through all four agents against fixture data.

03

SECTION

Idempotency, dedup, and not getting fleeced

Three places in the pipeline can duplicate work that costs money, and each one has its own guard. The Design agent SHA-256 hashes the final image prompt before calling fal.ai, so an identical prompt reuses the earlier image instead of paying for a duplicate. Scout runs both exact-match and Claude-powered semantic dedup before writing a brief, so near-duplicate trends don't flood the pipeline. Ledger puts a unique constraint on `etsy_order_id`, so polling can run as often as it likes without counting a sale twice.

When something fails, `structlog` emits a structured line, and a Slack webhook fires on any low-margin order. A separate daily cron sends a revenue and margin digest over Slack and email.

Generated artwork on a t-shirt product mockup
From trend brief to product: FLUX Pro 1.1 artwork on a Printify template.
04

SECTION

Margin math that has to stay right

Etsy returns receipts in the buyer's currency. Printify charges in USD. Etsy's fees depend on listing price, payment method, and shipping origin. True margin is `(USD sale − Etsy fees − print cost)`, and each of those three terms comes from a different source.

Ledger normalizes currencies from a daily rate snapshot, computes fees from Etsy's published rules, looks up print costs by SKU, and writes the final margin onto the row. That same row feeds both the daily digest and the low-margin Slack alert, so every dollar figure on the dashboard traces back to one place.

OUTCOME

A `HUMAN_REVIEW_ENABLED` gate holds every listing for a person to approve or reject before it publishes, while the other three agents keep working. It reports to Slack and deploys with a single `railway up`. Beyond the shared Postgres schema and the two per-language client libraries, the four agents share nothing: no central orchestrator, no shared runtime.

05

EXHIBITS

CAPTURE / 01 OF 03

AI-generated print artwork sample 01
Design agent output: FLUX Pro 1.1, 300dpi print-ready.

CAPTURE / 02 OF 03

AI-generated print artwork sample 02
Original artwork from a structured trend brief.

CAPTURE / 03 OF 03

Listing detail page with generated copy, compliance checklist, and a reject control
Claude-written title, description, and tags, checked against Etsy's compliance rules before it can publish.