Skip to main content
All Projects
COMPLETED

Conductor

Multi-tenant AI operations platform that runs business-critical pipelines as durable Temporal workflows: research, human approval, write, publish, with crash recovery, live streaming, and a replayable audit trail

Conductor screenshot 1

Role

Full Stack Developer

Team

Solo

Stack
Frontend
Next.js 16React 19React FlowTanStack QueryTailwind CSS v4Lenis
Backend
Fastify 5Node.jsBetter AuthDrizzleZodpino
Durable Execution
Temporal (TS SDK)LangGraph.jsVercel AI SDKOpenRouter
Data & Events
PostgreSQL 16Redis 7Socket.IO
Infra
Docker ComposeTurborepopnpm workspacesPlaywrightVitest
Challenges
  • Durable execution on Temporal so a crashed worker's in-flight step is re-dispatched and the run continues from its exact position, never a lost run
  • Human approval gates as Temporal signals plus condition(), holding zero worker slots while suspended instead of polling
  • Deterministic workflow sandbox: workflows/ do no I/O, read no env, and never call Date.now() or Math.random(); all side effects live in idempotent activities
  • Resume-from-step replays stored activity outputs, so finished steps never re-run and tokens are never re-spent
  • Structural multi-tenancy from the first migration: every domain row carries org_id from verified JWT claims, cross-org IDs resolve to 404
  • One generic interpreter workflow executes a versioned Zod-validated graph_spec shared by both templates and the React Flow canvas, so there is no second execution path
Insights
  • Temporal event history is the single execution source of truth; Postgres holds only read-side projections that no execution decision ever reads
  • AES-256-GCM crypto kept outside the shared barrel export so node:crypto never leaks into the web bundle
  • Bearer JWT verified statelessly via JWKS carries user id and active org id, avoiding a per-request database hit
  • Redis is ephemeral only: pub/sub for status and token streams plus a short cache, so a flush loses live tails but never durable state
  • Per-org OpenRouter key encrypted at rest and decrypted only inside the worker activity at call time, never logged or placed in Temporal or Redis payloads
  • Template parameter schema generates its own launch form, so the form and the contract cannot drift

Overview

Conductor is a multi-tenant AI operations platform that executes business-critical AI pipelines, research to human approval to write to publish, as durable Temporal workflows. Runs survive worker crashes and restarts, pause at human approval gates and resume on a click, stream live progress to a dashboard, and leave a complete, replayable audit trail. Each AI step is a specialist agent: a LangGraph.js sub-graph calling models through OpenRouter via the Vercel AI SDK, on the customer's own key.

The first target customer is AI agencies running content and SEO operations: teams executing dozens of pipelines a day who today lose runs to silent failures, babysit them by hand, and bolt approvals on with spreadsheets and Slack. The product sells outcomes, not architecture. Operators never see the words "Temporal" or "LangGraph", they see runs that complete, approvals that resume instantly, and a dashboard that never lies.

<2s

Approve to resume

0

Lost runs on crash

3

Apps: web, server, worker

BYOK

Per-org encrypted key


Architecture

Three deployable apps over a shared core, with Temporal as the execution source of truth:

apps/web ──HTTP/WS──> apps/server ──client──> Temporal ──dispatch──> apps/worker
                          │  └─subscribe─> Redis <─publish── activities ─┘
                          └─read──────────> PostgreSQL <─projection writes─┘
                                       activities ──LLM──> OpenRouter (AI SDK)
  • apps/web (Next.js dashboard) talks only to the server over HTTP and WebSocket with a bearer JWT. It owns no business logic and never touches Temporal, Postgres, or Redis.
  • apps/server (Fastify) hosts Better Auth organizations, REST routes, the Temporal client, the WebSocket relay, and the Redis subscriber. It runs no AI work and no long-lived jobs.
  • apps/worker (Temporal worker) keeps workflows/ as a deterministic sandbox and activities/ for every side effect: LangGraph agents, OpenRouter calls, Postgres and Redis writes.
  • packages/shared holds Zod schemas, types, and AES-256-GCM crypto; packages/db holds the Drizzle schema and org-scoped repository factories shared by server and worker so tenancy scoping is one codebase. Apps never import from each other.
Temporal history is the source of truth

Execution state lives in Temporal's event history and is never duplicated as authoritative data. Postgres rows (workflow_runs, activity_log) are read-side projections for the dashboard; no execution decision ever reads a projection. Redis is ephemeral: a flush loses live tails and warm caches, never durable state.


How A Run Works

  1. 1

    Launch from a template or canvas

    An operator opens a template (Blog Post Pipeline, SEO Brief, Competitor Research), fills a typed form, and hits launch. No code. The same graph_spec can be authored visually on the React Flow canvas at /canvas, validated live by the shared Zod schema and versioned with immutable history.

  2. 2

    Durable execution begins

    The generic interpreter workflow runs the versioned graph_spec, each node a Temporal activity wrapping a LangGraph.js sub-graph with per-activity retry policies and timeouts. A crashed worker's in-flight activity is re-dispatched automatically.

  3. 3

    Pause at the approval gate

    The run suspends on a Temporal signal plus condition(), holding no worker slot. The approver sees the full research findings and draft in their queue and clicks Approve or Reject. A 24-hour timeout expires the gate; every decision is recorded with who, what, and when.

  4. 4

    Resume and stream

    Approve resumes the run within two seconds; the writing step's LLM output streams token by token to the dashboard over Socket.IO. Reject ends the run gracefully.

  5. 5

    Recover or resume-from-step

    A failed run restarts from its last successful step using stored outputs, so research is not re-executed and tokens are not re-spent.


Key Features

Durable workflow execution

The content pipeline runs as Temporal activities with exponential-backoff retries. A SIGKILLed worker restarts and the run continues from its exact position, with the retry visible in step history.

Human-in-the-loop gates

Approval gates are Temporal signals plus condition(): zero polling, no worker slot held while suspended. The queue renders full context, resume lands in under two seconds, and a 24-hour timeout marks the gate expired.

One engine, two surfaces

A single interpreter workflow executes a versioned, Zod-validated graph_spec. Templates are code-curated catalog entries; the React Flow canvas is a visual editor over the same spec. There is no second execution path.

Real-time operations dashboard

Org-scoped run list with live status badges over WebSocket, a step timeline rail with live duration counters, streaming LLM output for the active step, and a per-step payload inspector.

Audit, replay, and resume

Immutable run history records every step's input, output, error, attempt count, and approval decision. Resume-from-step replays stored outputs so finished work never re-runs and tokens are never re-spent.

Organizations and teams

Better Auth organizations scope every page and API call. Owner and member roles, email-invitation accept flow, and a per-org OpenRouter key verified live against OpenRouter before it is stored encrypted.

Structural multi-tenancy

Every domain row carries a non-null org_id taken from verified JWT claims, never a request body. A member of one org gets a 404 for every resource of another, across every route and the WebSocket.

BYO key, self-hostable infra

There is no platform OpenRouter key: agents always run on the org's own key, decrypted only inside the worker activity. The stack is OSS-only (Postgres, Redis, Temporal OSS) with env-driven config.

Core invariants

Seven invariants prevent silent, catastrophic failure: deterministic workflow code, idempotent activities, human waits as signals never activities, Temporal history as the source of truth, org-scoping on every row, customer keys as secrets everywhere, and self-hostable infrastructure.

Determinism is not optional

Files in workflows/ must never do I/O, import Node built-ins, read env, or call Date.now() / Math.random(). Temporal replays workflow code against stored history, so any non-determinism corrupts recovery. Every side effect is pushed into an idempotent activity.


Outcome

Conductor demonstrates a production-grade durable-execution platform: a deterministic Temporal workflow sandbox with idempotent activities, human approval gates that hold no resources while suspended, resume-from-step that never re-spends tokens, and structural multi-tenancy enforced from the first migration. Two scripted proofs double as sales assets: the kill-the-worker reliability demo and the pause-resume approval demo, both driving the real product API end to end. All planned code units ship; remaining work is operator-gated deployment and design-partner testing.