Skip to main content

Feature: Expert Application

Last updated: 2026-06-04 (Pass-3 docs audit follow-up โ€” Tavus expert application cluster shipped 2026-06-03)

The Expert Application flow is how Humanity Protocol acquires new Experts: public applicants submit a form on the marketing site, complete an asynchronous Tavus video interview, and โ€” if their interview reviews well โ€” are promoted by a SuperAdmin into the platform as an active Expert. It is operationally distinct from the client onboarding flow.

Three audiences interact with this feature:

  • Applicants โ€” fill the marketing form, take the Tavus interview, then wait for an outcome email.
  • AMs / SuperAdmins โ€” review applications in the unified Ops surface (/ops/marketing/experts/*), retry interview invites, hard-delete spam entries, approve or decline applicants.
  • The Tavus integration โ€” drives the video interview, posts conversation
    • transcript webhooks back to humanwork-api, and atomically transitions the applicant to interview_completed so the review queue can pick them up.

What shippedโ€‹

PRChangeDate
#1369Original expert application form, AI screening, and ops pipeline (closes #1082 โ€” funnel: public apply form โ†’ async AI scoring โ†’ qualified / waitlisted โ†’ ops pipeline)2026-05-30
#1478Tavus video interviews wired into the expert application track (closes #1083) โ€” qualified applicants are sent a Tavus interview link instead of the legacy "approved" email2026-06-03
#1540Fixed Tavus expert application integration issues โ€” replica binding, applicant identity injected into conversational_context, conversation properties (recording + transcript callback URLs) tightened. Closes the regression that fell back to the qualified email when env was incomplete2026-06-03
#1524Ops review interface for interview_completed applicants โ€” /ops/marketing/experts gets an Interviews tab and a "Retry interview invite" action2026-06-03
#1519SuperAdmin hard-delete endpoint for expert applications + trash-icon UI on the list view โ€” lets ops scrub spam / duplicate submissions2026-06-03
#1565Flow polish โ€” send-to-interview action for waitlisted applicants, Approve transition wired to the post-interview status, LinkedIn-URL dedup on submit so resubmissions don't create new rows2026-06-03
#15605 Expert-onboarding email templates added to EmailService (closes #1554) โ€” application_received, interview_scheduled, application_approved, application_declined, welcome. See onboarding.md ยงExpert onboarding email templates2026-06-03

Flowโ€‹

[Marketing site]
โ”‚
โ”‚ POST /marketing/experts/application
โ–ผ
expert_applications row (status = pending)
โ”‚
โ”‚ async AI scoring (#1369)
โ–ผ
status = qualified | waitlisted | rejected
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ qualified โ†’ Tavus interview invite โ”‚
โ”‚ (#1478, #1540) โ”‚
โ”‚ email: expert.interview_scheduled โ”‚
โ”‚ status โ†’ invited โ”‚
โ”‚ โ”‚
โ”‚ waitlisted โ†’ SuperAdmin clicks โ”‚
โ”‚ "Send to interview" (#1565) โ”‚
โ”‚ โ†’ same path as qualified โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”‚ Applicant joins Tavus call
โ”‚ Tavus posts webhook โ†’ /tavus/webhooks/conversation-ended
โ”‚ Atomic status transition (#1083 / #1540): invited โ†’ interview_completed
โ–ผ
status = interview_completed
+ tavus_conversation_id, transcript_summary,
interview_completed_at populated
โ”‚
โ”‚ SuperAdmin reviews in /ops/marketing/experts (Interviews tab, #1524)
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Promote (POST .../promote) โ”‚ Decline (POST .../decline) โ”‚
โ”‚ status โ†’ approved โ”‚ status โ†’ rejected โ”‚
โ”‚ email: expert.application_approvedโ”‚ email: expert.application_declinedโ”‚
โ”‚ + create platform user (Expert) โ”‚ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”‚ Approved applicant logs into /workspace
โ–ผ
email: expert.welcome โ†’ active Expert

Status machineโ€‹

The full set of expert_applications.status values:

StatusSet byNext transitions
pendingPublic submitโ†’ qualified / waitlisted / rejected (AI scoring)
reviewingAI scoring in-flightโ†’ qualified / waitlisted / rejected
qualifiedAI scoringโ†’ invited (auto, Tavus invite sent) ยท โ†’ rejected (SA decline)
waitlistedAI scoringโ†’ invited (SA send-to-interview, #1565) ยท โ†’ rejected (SA decline) ยท โ†’ approved (SA promote โ€” legacy direct path)
invitedSystem (Tavus invite sent)โ†’ interview_completed (Tavus webhook) ยท โ†’ rejected
interview_completedTavus webhook (#1540)โ†’ approved (canonical post-interview path) ยท โ†’ rejected
approvedSA promoteterminal โ€” platform Expert created
rejectedSA declineterminal

Allowed transitions are enforced in MarketingService.promote() / decline() / sendWaitlistedToInterview() / retryInterviewInvite() โ€” see api/src/marketing/marketing.service.ts. The post-interview promotion path (interview_completed โ†’ approved) is described in the service's docstring as the canonical path; promoting directly from waitlisted remains for back-compat with applications taken before #1478 shipped.

Module locationsโ€‹

Backend (NestJS)โ€‹

  • api/src/marketing/ โ€” applicant-facing surface (form submit, status poll, waitlist rejoin) and the core MarketingService that owns the expert_applications row + status transitions.

    • marketing.controller.ts โ€” public POST /marketing/experts/application, GET /marketing/experts/application/status, GET /marketing/experts/application/:id, POST /marketing/experts/rejoin-waitlist.
    • marketing.service.ts โ€” submitExpertApplication, sendWaitlistedToInterview (#1565), retryInterviewInvite (#1524), promote (#1565, accepts interview_completed as entry status), decline.
    • entities/expert-application.entity.ts โ€” the expert_applications row (incl. Tavus fields added in the 1783/1784 migration series โ€” see Schema below).
  • api/src/admin/admin-marketing-leads.controller.ts โ€” SuperAdmin / AM-facing Ops surface. Mounts at /admin/marketing/leads/experts/*. Live routes:

    RoutePurpose
    GET /admin/marketing/leads/expertsList applicants (filterable by status โ€” Interviews tab uses status=interview_completed)
    GET /admin/marketing/leads/experts/:idDetail view
    PATCH /admin/marketing/leads/experts/:id/statusDirect status patch (back-compat)
    POST /admin/marketing/leads/experts/:id/promotePromote (interview_completed โ†’ approved, also accepts waitlisted/invited)
    POST /admin/marketing/leads/experts/:id/declineDecline โ†’ rejected
    POST /admin/marketing/leads/experts/:id/retry-inviteResend Tavus invite (#1524)
    POST /admin/marketing/leads/experts/:id/send-to-interviewForce waitlisted โ†’ invited + send Tavus invite (#1565)
    PATCH /admin/marketing/leads/experts/:id/thresholdAdjust per-application AI score threshold
    DELETE /admin/marketing/leads/experts/:idSuperAdmin hard-delete (#1519)
  • api/src/tavus/tavus.controller.ts โ€” Tavus webhook intake. POST /tavus/webhooks/conversation-ended is the entry point that atomically transitions invited โ†’ interview_completed (see #1540 fix). Related webhooks: POST /tavus/webhooks/function-call, POST /tavus/webhooks/transcript-ready. Replica enumeration: GET /tavus/replicas (gated by PlatformRolesGuard).

Schemaโ€‹

expert_applications table (TypeORM entity: api/src/marketing/entities/expert-application.entity.ts). Tavus-track columns were added by the following migrations (verify under api/migrations/):

MigrationAdds
1783000000001-AddTavusFieldsToExpertApplication.tstavus_conversation_id, tavus_replica_id, plus the invited/interview_completed status enum values
1783000000002-AddInterviewReminderSentField.tsinterview_reminder_sent_at โ€” for the reminder-nudge job on stale invited applicants
1783000000003-AddInviteSentAtToExpertApplication.tsinvite_sent_at โ€” anchors the reminder schedule and the retry-invite cooldown
1784000000001-AddInterviewCompletedAtToExpertApplication.tsinterview_completed_at โ€” set by the /tavus/webhooks/conversation-ended handler
1784000000002-AddTranscriptSummaryToExpertApplication.tstranscript_summary (JSONB) โ€” populated when the Tavus transcript webhook fires; surfaced in the Ops Interviews tab

The older marketing-side migration 1746000000009-ExpertApplicationR2Urls.ts (resume / portfolio object storage) and 1752200000010-ExpertApplicationWaitlistFields.ts (AI scoring + waitlist) predate the Tavus track but remain in effect.

Frontendโ€‹

  • Public form: frontend/src/app/(marketing)/apply/experts/* (and the /apply/experts/status poll page).
  • Ops surface: frontend/src/app/ops/marketing/experts/* โ€” list view, Interviews tab (#1524), per-application detail with Approve / Decline / Retry / Send-to-Interview / Delete actions.

The Expert workspace surface itself (/workspace/*) is not part of this doc โ€” it's covered by expert-workspace.md. Approved applicants only see /workspace/* after the expert.application_approved email lands them on the welcome flow.

Email side effectsโ€‹

Triggered by EmailService from MarketingService (#1560):

TransitionTemplate key
Submit (any pending create)expert.application_received
qualified / waitlisted + send-to-interview / retry-inviteexpert.interview_scheduled (includes the Tavus join URL)
promote โ†’ approvedexpert.application_approved
decline โ†’ rejectedexpert.application_declined
First successful login to /workspaceexpert.welcome

Templates live under api/src/email/templates/expert/. Copy changes go through PR review; see onboarding.md ยงExpert onboarding email templates.

  • docs/specs/tavus-integration.md โ€” the design surface for the wider Tavus integration (replica management, conversational context, webhook signatures, cost model). The expert application is one of two surfaces consuming Tavus today (the other is the client ร— Specialist onboarding call, tracked under #1379).
  • docs/decisions/tavus/ADR-0001-integration-approach.md โ€” chosen integration shape (CVI conversations + replicas, not standalone Persona Manager).
  • docs/decisions/tavus/ADR-0002-integration-test-deferral.md โ€” why integration tests against the live Tavus API are deferred and how that's compensated.
  • docs/features/onboarding.md โ€” client-side onboarding (distinct flow); the Expert email-templates table referenced from ยงExpert onboarding email templates is the same one consumed here.
  • Open follow-ups: #1202 (wire Tavus invite into promoteExpertApplication for legacy waitlisted-direct-promote โ€” now largely subsumed by #1565), #1363 (P2 design โ€” abstract the Tavus "management" layer that today lives partly in tavus/ and partly in marketing/).