the solomon engine — serverless processing architecture
A two-part voice interview processed through a self-healing pipeline. No always-on servers. The system runs only when an interview completes, recovers from failures automatically, and pages a human only for genuine dead-ends.
flowchart TD
subgraph ADMIN["ADMIN"]
A1["Create invite
POST /create-invite
name + email"]
A2["Email two links
to user"]
A1 --> A2
end
subgraph SB1["SUPABASE"]
direction TB
DB1[("vi_sessions
vi_invites
created")]
end
A1 -->|"creates session + invite"| DB1
A1 -->|"returns part_1_url + part_2_url"| A2
subgraph USER["USER"]
U1["Clicks Part 1 link"]
U2["Voice interview
Pain Points & Workflow
~6 min"]
U3["Clicks Part 2 link"]
U4["Voice interview
Work Style & Tools
~6 min"]
U1 --> U2 --> U3 --> U4
end
A2 -.->|"sends links"| U1
subgraph EL["ELEVENLABS"]
EL1["Agent 1
var_session_id baked in"]
EL2["Agent 2
var_session_id baked in"]
end
U2 -->|"talks to"| EL1
U4 -->|"talks to"| EL2
subgraph DISPATCH["SUPABASE EDGE FUNCTION"]
D1["Dispatcher
/dispatcher"]
D2{"Both halves
received?"}
D1 --> D2
end
EL1 -->|"post-call webhook
+ dynamic_variables"| D1
EL2 -->|"post-call webhook
+ dynamic_variables"| D1
subgraph SB2["SUPABASE DB"]
DB2[("vi_transcripts
filed by session_id")]
DB3[("vi_jobs
queued")]
end
D1 -->|"verify sig + file transcript"| DB2
D2 -->|"No — wait"| DB2
D2 -->|"Yes — enqueue"| DB3
subgraph WORKER["RAILWAY JOB"]
W1["Claim job"]
W2["Stage 1: Extract
Claude API
JSON extraction"]
W3{"Validate
extraction"}
W4["Stage 2: Generate
Claude API
markdown instructions"]
W5{"Validate
output"}
W6["Write deliverable"]
W1 --> W2 --> W3
W3 -->|"pass"| W4 --> W5
W5 -->|"pass"| W6
end
DB3 -->|"trigger via Railway API"| W1
subgraph SB3["SUPABASE DB"]
DB4[("vi_deliverables
review_status: pending")]
DB5[("vi_sessions
status: complete")]
end
W6 -->|"atomic write"| DB4
W6 -->|"mark complete"| DB5
subgraph REVIEW["ADMIN"]
R1["Review deliverable"]
R2{"Approve?"}
R3["Deploy instructions"]
R4["Request re-interview"]
R1 --> R2
R2 -->|"yes"| R3
R2 -->|"no"| R4
end
DB4 -.->|"admin reviews"| R1
subgraph FAIL["FAILURE + RECOVERY"]
F1["Job fails"]
F2["Increment retry_count"]
F3{"retry_count
< 5?"}
F4["Back to ready_to_process"]
F5["Mark FAILED
+ alert admin"]
end
W3 -->|"fail"| F1
W5 -->|"fail"| F1
F1 --> F2 --> F3
F3 -->|"yes"| F4
F3 -->|"no"| F5
subgraph SWEEPER["SUPABASE CRON EDGE FUNCTION"]
S1["Sweeper
every 5 min"]
S2["Re-enqueue stuck jobs"]
S3["Flag orphan sessions"]
S1 --> S2
S1 --> S3
end
F4 -.->|"sweeper picks up"| S2
S2 -->|"create new vi_job + trigger worker"| DB3
classDef adminNode fill:#f3e8ff,stroke:#7c3aed,color:#5b21b6,stroke-width:2px
classDef userNode fill:#ecfeff,stroke:#0891b2,color:#155e75,stroke-width:2px
classDef systemNode fill:#ecfdf5,stroke:#059669,color:#065f46,stroke-width:2px
classDef dbNode fill:#f0fdf4,stroke:#10b981,color:#065f46,stroke-width:2px
classDef failNode fill:#fef2f2,stroke:#dc2626,color:#991b1b,stroke-width:2px
classDef elNode fill:#fffbeb,stroke:#f59e0b,color:#92400e,stroke-width:2px
classDef railNode fill:#faf5ff,stroke:#9333ea,color:#581c87,stroke-width:2px
classDef decisionNode fill:#fefce8,stroke:#d97706,color:#92400e,stroke-width:2px
class A1,A2,R1,R3,R4 adminNode
class U1,U2,U3,U4 userNode
class D1,S1,S2,S3 systemNode
class DB1,DB2,DB3,DB4,DB5 dbNode
class F1,F2,F4,F5 failNode
class EL1,EL2 elNode
class W1,W2,W4,W6 railNode
class D2,W3,W5,R2,F3 decisionNode
style ADMIN fill:transparent,stroke:#7c3aed,stroke-width:2px,stroke-dasharray:5 5,color:#7c3aed
style USER fill:transparent,stroke:#0891b2,stroke-width:2px,stroke-dasharray:5 5,color:#0891b2
style EL fill:transparent,stroke:#f59e0b,stroke-width:2px,stroke-dasharray:5 5,color:#f59e0b
style DISPATCH fill:transparent,stroke:#10b981,stroke-width:2px,stroke-dasharray:5 5,color:#10b981
style WORKER fill:transparent,stroke:#9333ea,stroke-width:2px,stroke-dasharray:5 5,color:#9333ea
style REVIEW fill:transparent,stroke:#7c3aed,stroke-width:2px,stroke-dasharray:5 5,color:#7c3aed
style FAIL fill:transparent,stroke:#dc2626,stroke-width:2px,stroke-dasharray:5 5,color:#dc2626
style SWEEPER fill:transparent,stroke:#10b981,stroke-width:2px,stroke-dasharray:5 5,color:#10b981
style SB1 fill:transparent,stroke:#10b981,stroke-width:1px,stroke-dasharray:3 3,color:#10b981
style SB2 fill:transparent,stroke:#10b981,stroke-width:1px,stroke-dasharray:3 3,color:#10b981
style SB3 fill:transparent,stroke:#10b981,stroke-width:1px,stroke-dasharray:3 3,color:#10b981
flowchart LR
AH["awaiting_halves"]
RTP["ready_to_process"]
P["processing"]
C["complete"]
F["failed"]
AH -->|"both halves received"| RTP
RTP -->|"worker claims job"| P
P -->|"deliverable written"| C
P -->|"error + retries left"| RTP
P -->|"retry cap exhausted"| F
RTP -->|"retry cap exhausted"| F
classDef waiting fill:#ecfeff,stroke:#0891b2,color:#155e75,stroke-width:2px
classDef active fill:#fffbeb,stroke:#f59e0b,color:#92400e,stroke-width:2px
classDef done fill:#ecfdf5,stroke:#059669,color:#065f46,stroke-width:2px
classDef dead fill:#fef2f2,stroke:#dc2626,color:#991b1b,stroke-width:2px
class AH waiting
class RTP,P active
class C done
class F dead
5 prevents infinite loops on unprocessable transcripts.
Admin is alerted only on permanent failed status.