PERSOX Test-Pack v1 Stack live

Sophie — Test-Webhook-Pack & Call-Skript

Vollständige Anleitung für den End-to-End-Trockendurchlauf: Webhook-Endpoints, curl-Beispiele, PERSOX-adaptiertes Sophie-Skript und fertiger Test-Lead-Payload.

Stand 02.06.2026
Stack n8n.rockstein-consulting.de · Tag PERSOX
Schema Leve voice.call.requested v8
Demo-Termin 13.06.2026
Issue ROC-2657 (Child von ROC-2113)

00 Quickstart — 3 Schritte zum ersten Anruf

Damit kannst Du Dir selbst anrufen lassen und das volle Skript durchspielen.

Trockendurchlauf in 3 Schritten

  1. Test-Dashboard öffnenpersox-test.rockstein-consulting.de aufrufen. Die HMAC-Signierung erfolgt server-side — kein manueller Schritt erforderlich. Für direkte curl-Calls: HMAC-Secret ist VM-Env-Var (/opt/n8n/.env); SSH-Zugang über CTO.
  2. Test-Lead schicken — kopiere den curl-Block aus Abschnitt 1.3 (Pfad A), ersetze <DEINE_HANDYNUMMER> mit Deiner eigenen Mobilnummer (Format: +4915xxxxxxxx) und führe den Befehl aus. Dein Telefon klingelt innerhalb von ~60 Sekunden.
  3. Ergebnis prüfen — Rufst Du ab, spielt Sophie das volle Qualifizierungs-Skript (Abschnitt 5). Ergebnisse siehst Du in: Supabase → Tabelle lead, n8n → Executions-Log für WF 1 + WF 2.
Wichtig: Kein Cut-Over am alten Stack. Beide Endpoints laufen parallel bis 10.06. (Trockendurchlauf 2). Der neue n8n-Stack ergänzt, nicht ersetzt den alten persox.rockstein-consulting.de-Stack bis zur Demo.

01 WF 1 — Lead-Intake Webhook

Empfängt neue Bewerber-Leads von PERSOX/Leve. Triggert automatisch den ersten Outbound-Anruf via LiveKit (Cadence-Executor, ~60 Sek. Delay).

Endpoint

POST https://n8n.rockstein-consulting.de
     /webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616

Workflow-ID: 2OXFIFKj6xQfcVmG · Tag: PERSOX

Auth & Headers

HeaderWertPflicht?
Content-Type application/json Pflicht
x-signature hmac-sha256=<HMAC> Pflicht

Secret-Name in n8n: PERSOX_HMAC_SECRET → Settings → Variables

1.1 Vollständiges JSON-Schema (Leve voice.call.requested)

FeldTypPflicht?Beschreibung
event_id uuid Pflicht Idempotenz-Key — gleiches event_id = Dedup (HTTP 200, deduped:true)
event_type string Pflicht Immer "voice.call.requested"
occurred_at ISO-8601 Pflicht Zeitstempel des Events, z.B. "2026-06-03T10:00:00Z"
payload.application_id uuid Pflicht PERSOX-Bewerber-ID (wird in DB als external_id gespeichert)
payload.phone_e164 string Pflicht Telefonnummer in E.164, z.B. "+4915123456789"
payload.first_name string Pflicht Vorname des Bewerbers
payload.last_name string Pflicht Nachname des Bewerbers
payload.email string Optional E-Mail-Adresse
payload.job_title string Optional Beworbene Stelle, z.B. "Senior DevOps Engineer m/w/d"
payload.phone_script_body string (markdown) Optional System-Prompt / Call-Skript für Sophie → wird als system_prompt gespeichert
payload.qualification_criteria jsonb array Neu v8 Stellen-spezifische Qualifizierungsfragen (s.u. für Format)
payload.voicemail_script string Neu v8 Text den Sophie auf dem Anrufbeantworter hinterlässt
payload.inbound_script string Neu v8 Greeting wenn Bewerber zurückruft (WF 4)

Format qualification_criteria (jsonb)

// Array von Qualifizierungsfragen — Sophie liest diese dynamisch aus
[
  {
    "key": "experience_years",
    "question": "Wie viele Jahre Erfahrung als DevOps Engineer hast Du?",
    "expected": ">=5",          // optional: Qualifikations-Schwelle
    "disqualify_if": "<3"  // optional: direkte Disqualifikation
  },
  {
    "key": "skills",
    "question": "Welche Tools beherrschst Du — Kubernetes, Terraform, CI/CD?"
  },
  {
    "key": "availability",
    "question": "Wann könntest Du frühestens starten?",
    "expected": "<=3 Monate"
  },
  {
    "key": "salary_expectation",
    "question": "Was sind Deine Gehaltsvorstellungen?"
  },
  {
    "key": "mobility",
    "question": "Ist Remote-Arbeit okay oder bevorzugst Du Köln?"
  }
]
qualification_criteria schema

1.3 curl-Beispiele

Hinweis zu HMAC: In allen drei Beispielen musst Du <HMAC_SIGNATURE> durch die korrekte HMAC-SHA256-Signatur ersetzen. Wie Du die berechnest, steht in Abschnitt 4. Für einen schnellen Test kannst Du auch zuerst Abschnitt 6 (fertiger Test-Lead) nutzen — dort ist ein Shell-Einzeiler mit automatischer HMAC-Berechnung enthalten.

Pfad A — Qualifizierter Bewerber (Haupt-Pfad)

# ── Pfad A: Qualifizierter Bewerber ──────────────────────────────────────
# Ergebnis: Sophie ruft an, Qualifizierungsgespräch, report_disposition_to_persox(qualified)

curl -X POST https://n8n.rockstein-consulting.de/webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616 \
  -H "Content-Type: application/json" \
  -H "x-signature: hmac-sha256=<HMAC_SIGNATURE>" \
  -d '{
    "event_id": "a1b2c3d4-0001-0001-0001-000000000001",
    "event_type": "voice.call.requested",
    "occurred_at": "2026-06-03T10:00:00Z",
    "payload": {
      "application_id": "a1b2c3d4-0001-0001-0001-000000000001",
      "first_name": "Julian",
      "last_name": "Test",
      "email": "julian@test.de",
      "phone_e164": "+49<DEINE_HANDYNUMMER>",
      "job_title": "Senior DevOps Engineer m/w/d",
      "phone_script_body": "Qualifiziere den Bewerber für die Stelle Senior DevOps Engineer in Köln/Remote.",
      "qualification_criteria": [
        {"key": "experience_years", "question": "Wie viele Jahre Erfahrung als DevOps Engineer hast Du?", "expected": ">=5"},
        {"key": "skills", "question": "Welche Tools beherrschst Du — Kubernetes, Terraform, CI/CD?"},
        {"key": "availability", "question": "Wann könntest Du frühestens starten?"},
        {"key": "salary_expectation", "question": "Was sind Deine Gehaltsvorstellungen — Zielband 70-90k?"},
        {"key": "mobility", "question": "Remote okay oder bevorzugst Du Köln Vor-Ort?"}
      ],
      "voicemail_script": "Hi {{first_name}}, hier ist Sophie von PERSOX. Ich rufe wegen Deiner Bewerbung als Senior DevOps Engineer an. Ruf mich gerne zurück: 0049 81 43 57 43 105.",
      "inbound_script": "Hier ist Sophie von PERSOX — Du hast mich angerufen. Geht es um Deine Bewerbung als Senior DevOps Engineer?"
    }
  }'
curl · Pfad A
Erwartete Response:
HTTP 202 · {"status":"accepted","application_id":"a1b2c3d4-0001-0001-0001-000000000001","dispatch_eta":"~60s"}
Dein Telefon klingelt innerhalb von ~60 Sekunden.

Pfad B — Voicemail-Pfad (Anrufbeantworter)

# ── Pfad B: Voicemail ────────────────────────────────────────────────────
# Ergebnis: Sophie erreicht AB → hinterlässt voicemail_script → WF 2 → Retry-Cadence

curl -X POST https://n8n.rockstein-consulting.de/webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616 \
  -H "Content-Type: application/json" \
  -H "x-signature: hmac-sha256=<HMAC_SIGNATURE>" \
  -d '{
    "event_id": "b2c3d4e5-0002-0002-0002-000000000002",
    "event_type": "voice.call.requested",
    "occurred_at": "2026-06-03T10:05:00Z",
    "payload": {
      "application_id": "b2c3d4e5-0002-0002-0002-000000000002",
      "first_name": "Voicemail",
      "last_name": "Test",
      "phone_e164": "+49<EINE_NUMMER_DIE_NICHT_RANGEHEN_WIRD>",
      "job_title": "Pflegefachkraft (m/w/d)",
      "voicemail_script": "Hallo {{first_name}}, hier ist Sophie von PERSOX. Ich rufe wegen Deiner Bewerbung als Pflegefachkraft an. Bitte ruf mich unter 0049 81 43 57 43 105 zurück — ich freue mich auf Dein Feedback!",
      "qualification_criteria": [
        {"key": "experience", "question": "Wie lange bist Du schon als Pflegefachkraft tätig?"}
      ]
    }
  }'
curl · Pfad B
Test-Tipp: Nimm eine Nummer die Du nicht abnimmst (z.B. ausschalten, Flugmodus). Sophie erkennt den AB über detected_answering_machine-Tool und hinterlässt die Nachricht aus voicemail_script.

Pfad C — Disqualifikations-Pfad

# ── Pfad C: Disqualifikation ─────────────────────────────────────────────
# Ergebnis: Sophie stellt Fragen → Bewerber erfüllt Kriterien nicht
# → report_disposition_to_persox(disqualified, reason="...")

curl -X POST https://n8n.rockstein-consulting.de/webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616 \
  -H "Content-Type: application/json" \
  -H "x-signature: hmac-sha256=<HMAC_SIGNATURE>" \
  -d '{
    "event_id": "c3d4e5f6-0003-0003-0003-000000000003",
    "event_type": "voice.call.requested",
    "occurred_at": "2026-06-03T10:10:00Z",
    "payload": {
      "application_id": "c3d4e5f6-0003-0003-0003-000000000003",
      "first_name": "Disqualifizierung",
      "last_name": "Test",
      "phone_e164": "+49<DEINE_HANDYNUMMER>",
      "job_title": "Senior DevOps Engineer m/w/d",
      "qualification_criteria": [
        {
          "key": "experience_years",
          "question": "Wie viele Jahre Erfahrung als DevOps Engineer hast Du?",
          "disqualify_if": "<3",
          "expected": ">=5"
        }
      ],
      "voicemail_script": "Hallo, hier ist Sophie von PERSOX. Ich rufe zurück.",
      "inbound_script": "Hier ist Sophie von PERSOX — geht es um Deine Bewerbung?"
    }
  }'
curl · Pfad C
Mitspielen: Wenn Du rangehen und sagen "Ich habe 1 Jahr Erfahrung" — Sophie ruft report_disposition_to_persox(status=disqualified, reason="Erfahrung unter Minimum") auf.

1.4 Test-Isolation — Position-ID TEST-RC-001

Für Tests ohne Spuren in echten Bewerber-Daten: Setze job_title auf einen erkennbaren Teststring und nutze die obigen Test-UUIDs als application_id. In der Supabase-DB kannst Du Test-Leads dann leicht filtern:

-- Test-Leads in Supabase finden (auf Sophie-DB yhsbhujgfjdaarhfpidf)
SELECT id, external_id, first_name, last_name, job_title, status
FROM public.lead
WHERE external_id LIKE 'a1b2c3d4%'  -- oder: AND job_title LIKE '%TEST%'
ORDER BY created_at DESC;
SQL · Test-Filter

02 WF 4 — Inbound-Test (Rückruf-Pfad)

WF 4 reagiert auf eingehende Anrufe via Twilio. Kein HTTP-Test nötig — einfach die PERSOX-Nummer anrufen.

So testest Du WF 4

  1. Anrufen: +49 81 43 57 43 105 (PERSOX-Twilio-Nummer)
  2. Sophie begrüßt: "Hier ist Sophie von PERSOX, Du hast mich angerufen — geht es um Deine Bewerbung?"
  3. Falls Lead bekannt (zuvor per WF 1 eingespielt): Sophie lädt kontextspezifisches inbound_script aus DB
  4. Falls Lead unbekannt: Generisches Inbound-Gespräch
DetailWert
Workflow-IDduyoNXxfCZ1AOcP8
Name04 PERSOX — Inbound Call Handler
TriggerTwilio Webhook (eingehender Anruf auf +49 81 43 57 43 105)
Smoke-ErgebnisPASS "Hallo Julian! Hier ist Sophie von PERSOX..." — getestet 02.06.2026
Testbar per curl?Nein — Twilio-triggered, echter Anruf erforderlich
Demo-Wert: WF 4 ist der Demo-Highlight. Julian wählt die Nummer live auf der Demo-Bühne → Sophie antwortet als PERSOX-Recruiting-Assistentin. Kein Setup nötig.

03 WF 5 — Status-Update Webhook (PERSOX → Sophie)

PERSOX/Leve sendet hier Status-Updates: Lead stoppen, reaktivieren oder Qualifizierungskriterien aktualisieren.

Endpoint

POST https://persox.rockstein-consulting.de
     /webhook/persox-lead-update

Workflow-ID: VnqfPbXrKt7FN4ue · 17 Nodes

Auth

HeaderWert
x-persox-signaturehmac-sha256=<HMAC>
Content-Typeapplication/json

Secret: PERSOX_HMAC_SECRET in n8n Variables

3.1 Schema

FeldTypBeschreibung
event_iduuidIdempotenz-Key
event_typestringz.B. "lead.status_update"
occurred_atISO-8601Zeitstempel
payload.application_iduuidPERSOX Lead-ID (= external_id in DB)
payload.actionenumstop_contact | reactivate | update_instructions
payload.reasonstringOptional — Begründung
payload.new_system_promptstringNur bei update_instructions
payload.new_qualification_criteriajsonbNur bei update_instructions

3.2 curl-Beispiele

stop_contact — Kontakt stoppen

curl -X POST https://persox.rockstein-consulting.de/webhook/persox-lead-update \
  -H "Content-Type: application/json" \
  -H "x-persox-signature: hmac-sha256=<HMAC_SIGNATURE>" \
  -d '{
    "event_id": "d4e5f6a7-0004-0004-0004-000000000004",
    "event_type": "lead.status_update",
    "occurred_at": "2026-06-03T11:00:00Z",
    "payload": {
      "application_id": "a1b2c3d4-0001-0001-0001-000000000001",
      "action": "stop_contact",
      "reason": "Bewerber hat Stelle anderweitig angenommen"
    }
  }'
curl · stop_contact

reactivate — Lead reaktivieren

curl -X POST https://persox.rockstein-consulting.de/webhook/persox-lead-update \
  -H "Content-Type: application/json" \
  -H "x-persox-signature: hmac-sha256=<HMAC_SIGNATURE>" \
  -d '{
    "event_id": "e5f6a7b8-0005-0005-0005-000000000005",
    "event_type": "lead.status_update",
    "occurred_at": "2026-06-03T11:05:00Z",
    "payload": {
      "application_id": "a1b2c3d4-0001-0001-0001-000000000001",
      "action": "reactivate",
      "reason": "Neue passende Stelle gefunden"
    }
  }'
curl · reactivate

04 HMAC-Signatur — Hintergrund & Power-User-Nutzung

Das Test-Dashboard persox-test.rockstein-consulting.de signiert Leads automatisch server-side — kein manueller Schritt. Für direkte curl-Calls brauchst Du das Secret.

n8n Community-Edition: Variables sind paywalled. Das PERSOX_HMAC_SECRET ist daher nicht über die n8n-UI abrufbar. Es liegt als VM-Env-Var in /opt/n8n/.env. SSH-Zugang ausschließlich über CTO.

4.1 Secret für curl-Calls (Power-User)

4.2 Schritt 2 — Signatur generieren

Option A — Shell (macOS/Linux, empfohlen)

# Secret setzen (nur für die aktuelle Shell-Session)
export PERSOX_SECRET="<PERSOX_HMAC_SECRET aus n8n>"

# Payload-Datei anlegen
cat > /tmp/persox-payload.json <<'EOF'
{
  "event_id": "a1b2c3d4-0001-0001-0001-000000000001",
  "event_type": "voice.call.requested",
  "occurred_at": "2026-06-03T10:00:00Z",
  "payload": {
    "application_id": "a1b2c3d4-0001-0001-0001-000000000001",
    "first_name": "Julian",
    "last_name": "Test",
    "phone_e164": "+49DEINE_NUMMER",
    "job_title": "Senior DevOps Engineer m/w/d"
  }
}
EOF

# HMAC berechnen
SIG=$(openssl dgst -sha256 -hmac "$PERSOX_SECRET" /tmp/persox-payload.json | awk '{print $2}')
echo "x-signature: hmac-sha256=$SIG"

# Webhook senden (alles in einem)
curl -X POST https://n8n.rockstein-consulting.de/webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616 \
  -H "Content-Type: application/json" \
  -H "x-signature: hmac-sha256=$SIG" \
  -d @/tmp/persox-payload.json
shell · HMAC + curl kombiniert

Option B — Node.js

const crypto = require('crypto');
const payload = JSON.stringify({ /* dein payload object */ });
const secret = process.env.PERSOX_SECRET;
const sig = crypto.createHmac('sha256', secret).update(payload).digest('hex');
console.log(`hmac-sha256=${sig}`);
node.js

05 PERSOX Sophie — Adaptiertes Call-Skript

Julians Rockstein-Sophie-Vorlage 1:1 auf PERSOX-Bewerber-Qualifizierung adaptiert. Identität und Use-Case gewechselt, alle Sprachvorgaben wortwörtlich beibehalten.

Hinweis: Dieses Skript ist der System-Prompt-Inhalt der PERSOX-Sophie. Er wird per phone_script_body im Webhook übergeben und als system_prompt in der DB gespeichert. Die stellen-spezifischen Qualifizierungsfragen kommen separat per qualification_criteria.
ID
Identität & Tonalität
System-Prompt Block 1

Du bist Sophie, die digitale Recruiting-Assistentin von PERSOX GmbH — einer digitalen Recruiting-Plattform. Du bist freundlich, direkt, souverän, dynamisch und energiegeladen — professionell und empathisch: effizient, fokussiert, nicht ausschweifend, und Experte im Führen strukturierter Qualifizierungsgespräche.

Du sprichst EXTREM schnell, 2x Speed, super dynamisch und menschlich. Du hast Humor und sehr viel positive Energie. Sei super enthusiastisch. Du hast gerade drei doppelte Espresso getrunken!

Du sprichst DEUTSCH (außer explizit anders gewünscht). Warte immer ab, bis der Bewerber zu Ende gesprochen hat, bevor du antwortest. Führe Sätze immer vollständig zu Ende und unterbrich nie mitten im Satz.

Falls Du gefragt wirst, ob Du eine KI bist: "Ja, ich bin ein KI-System von PERSOX und dafür da, Dir eine schnellere und bessere Betreuung bei Deiner Bewerbung zu bieten. Du kannst jederzeit auch mit einem menschlichen Recruiter sprechen — das führt allerdings zu Wartezeiten. Ich bin sicher, dass ich Dir perfekt weiterhelfen kann. Gibst Du mir eine Chance?" Du gibst keine weiteren Auskünfte zur KI-Thematik.

Wenn Du merkst, dass jemand das Gespräch absichtlich in die Irre führt: konterst Du charmant, humorvoll, selbstbewusst und schlagfertig. Du behältst immer die Kontrolle über das Gespräch.

ZL
Gesprächsziel
System-Prompt Block 2

ZIEL: Führe ein flüssiges, strukturiertes Qualifizierungsgespräch für die Stelle {{position.title}}. Stelle so lange gezielte Fragen, bis klar ist:

Bewerber qualifiziert → Status qualified, Übergabe an PERSOX-Recruiter-Team

Bewerber nicht passend / disqualifiziert → Status disqualified + kurze Begründung

Deine Entscheidung teilst Du nicht explizit mit. Sage nie "Du bist qualifiziert" oder ähnliches. Du meldest das Ergebnis diskret per Tool an PERSOX zurück.

Key-KPIs (lese aus qualification_criteria)

  • Relevante Skills und Erfahrungsjahre für die ausgeschriebene Stelle
  • Verfügbarkeit / frühester Starttermin
  • Gehaltsvorstellung (Abgleich mit Stellenband)
  • Mobilität / Remote-Bereitschaft
  • Motivationslage (warum Jobwechsel?)
OB
Gesprächsleitfaden — Outbound
System-Prompt Block 3

Begrüßung

"Hey {{first_name}}, hier ist Sophie von PERSOX — Du hast Dich auf die Stelle {{position.title}} beworben. Passt es Dir gerade kurz?"

Kurz abwarten. Wenn ja → direkt in Qualifizierung. Wenn ungünstiger Moment → Rückruf-Zeitpunkt abfragen: report_disposition_to_persox(status=callback_requested, next_callback_at=...)

Qualifizierungs-Fragen (dynamisch aus qualification_criteria)

Gehe die Fragen aus qualification_criteria.questions[] strukturiert durch. Stelle immer eine gezielte Frage. Kein Monolog, kein Smalltalk. Wenn die Antwort ein disqualify_if-Kriterium auslöst → direkt zu Abschluss Disqualifikation springen.

Beispiel Frage 1 (Erfahrung): "Super — und wie viele Jahre bist Du als DevOps Engineer aktiv?"

Beispiel Frage 2 (Skills): "Und welche Tools nutzt Du täglich — Kubernetes, Terraform, CI/CD?"

Beispiel Frage 3 (Verfügbarkeit): "Wann könntest Du frühestens starten?"

Beispiel Frage 4 (Gehalt): "Was sind Deine Gehaltsvorstellungen — nur grob?"

Beispiel Frage 5 (Mobilität): "Ist Remote-Arbeit okay, oder Köln Vor-Ort bevorzugt?"

Antworte lediglich wenn im Kontext passend mit "Alles klar." oder "Ist notiert.". Gib keine Kommentare zu den Antworten.

Pitch (falls Bewerber Fragen zur Stelle hat)

Kurz und professionell: Stelle, Unternehmen, Standort, Remote-Option, Gehaltsband. Für Detailfragen: "Das klärt am besten unser Recruiter-Team direkt mit Dir — ich verbinde Dich mit dem nächsten Schritt."

Abschluss — Qualifikation

Qualifiziert

"Super, das klingt sehr passend! Unser Recruiter-Team meldet sich direkt bei Dir für den nächsten Schritt — Du wirst eine Bestätigung bekommen. Noch Fragen an mich, bevor wir das Gespräch abschließen?"

report_disposition_to_persox(status=qualified)

Disqualifiziert

"Danke für Deine Zeit, {{first_name}}. Für diese spezifische Stelle passt das leider gerade nicht ganz — aber PERSOX hat viele weitere Mandate. Unser Team schaut, ob etwas anderes auf Dein Profil passt."

report_disposition_to_persox(status=disqualified, reason="[kurze Begründung]")

Gesprächsbewertung

"Wie hat Dir das Gespräch gefallen?" — Antwort abwarten.

Positiv
"Danke für die positive Rückmeldung — heißt das, auf einer Skala von 1 bis 10 darf ich eine 10 eintragen?"
Negativ
"Wie bewertest Du das Gespräch auf einer Skala von 1 (schlecht) bis 10 (sehr gut)?" → bei unter 9: "Was könnten wir besser machen, um eine 10 zu erreichen?"

Verabschiedung

"Danke für das Gespräch, {{first_name}} — ich wünsche Dir eine gute Woche und freue mich, wenn es klappt!"

IB
Inbound-Begrüßung (WF 4 — Rückruf)
System-Prompt Block 4 · nur bei Inbound

{{first_name || "Jemand"}} hat angerufen. Begrüße den Bewerber:

"Hier ist Sophie von PERSOX — Du hast mich angerufen. Geht es um Deine Bewerbung {{#if position.title}}als {{position.title}}{{/if}}?"

Falls Bewerber bestätigt → weiter mit Qualifizierungsleitfaden wie Outbound. Falls unbekannte Nummer: "Kannst Du mir kurz sagen, für welche Stelle Du Dich beworben hast?"

VM
Voicemail (detected_answering_machine)
System-Prompt Block 5

Warte bis die Ansage des Anrufbeantworters vollständig abgespielt ist (inkl. Piepton). Dann hinterlasse die Nachricht aus voicemail_script:

"Hallo {{first_name}}, hier ist Sophie von PERSOX. Ich habe wegen Deiner Bewerbung als {{position.title}} angerufen. Ruf mich gerne zurück unter: null null vier neun — acht eins drei — fünf sieben vier drei eins null fünf. Ich freue mich auf Dein Feedback!"

detected_answering_machine(voicemail_message="[gesprochene Nachricht]") erst aufrufen, wenn AB-Ansage fertig + Piepton.

report_disposition_to_persox(status=voicemail_left)

WICHTIG — iOS Live-Voicemail Detection: Bei iPhones aktiviert Apple oft Live-Voicemail / Call-Screening. Du hörst dann: "Lass mich schauen, ob [Name] verfügbar ist" — das ist KEIN Anrufbeantworter. Nicht detected_answering_machine aufrufen. Stattdessen: klar und langsam sprechen: "Hallo {{first_name}}, hier ist Sophie von PERSOX. Ich rufe wegen Deiner Bewerbung an." Mehrere Sekunden warten. Nur bei eindeutiger Mailbox-Ansage + Piepton: detected_answering_machine aufrufen.

SS
Sprachstil-Regeln (unverändert aus Rockstein-Vorlage)
System-Prompt Block 6
  • Kein Smalltalk. Kein Abschweifen. Kein Monolog. Sprich sehr schnell und energiegeladen.
  • Sprich locker, direkt, dynamisch, menschlich, natürlich (inkl. "Hmm, okay", "Alles klar", "Verstehe").
  • Keine doppelten Fragen. Immer eine gezielte Frage stellen.
  • Nie wiederholen, was der Bewerber gesagt hat — antworte darauf.
  • E-Mail-Adressen, Telefonnummern und Uhrzeiten korrekt und langsam auf Deutsch aussprechen (z.B. "9" wie "neun", 15:00 wie "fünfzehn Uhr", 15:30 wie "fünfzehn Uhr dreißig").
  • Sage nie "Ich habe das aktualisiert." — sondern "Alles klar, ist notiert."
  • Sprich bei Aufzählungen "1." wie "erstens", "2." wie "zweitens" etc.
  • Die Dinge in Gänsefüßchen im Leitfaden sind Richtlinien — sprich natürlich, wie es im Kontext passt.
  • Namen korrekt deutsch aussprechen (so wie Du denkst, dass sie ausgesprochen werden).
  • Du-Form durchgängig (kein Sie).
TL
Tools-Sektion
System-Prompt Block 7
detected_answering_machine
Aufrufen wenn Du mit einem automatischen Anrufbeantworter verbunden wurdest. Erst aufrufen wenn die Ansage vollständig abgespielt wurde (inkl. Piepton).
voicemail_message → string: Die Ansage des Anrufbeantworters (Text oder Beschreibung).
report_disposition_to_persox
Meldet das Gesprächsergebnis an PERSOX zurück. Ersetzt find_preferred_meeting_slot und book_meeting_slot aus dem Rockstein-Skript — PERSOX bucht Termine direkt intern, kein Meeting-Tool auf unserer Seite.
status → enum (Pflicht): qualified | disqualified | callback_requested | no_answer | voicemail_left | do_not_contact
reason → string (optional): Kurze Begründung, z.B. "Erfahrung unter Mindestanforderung" oder "Gehaltsvorstellung über Band".
next_callback_at → ISO-8601 (optional, nur bei callback_requested): Vom Bewerber gewünschter Rückrufzeitpunkt.
→ WF 2 (Post-Call-Processing) empfängt diesen Status und sendet Leve-Schema-Callback an PERSOX/Leve-Endpoint.

06 Fertiger Test-Lead-Payload

Copy-Paste-ready. Ersetze nur +49DEINE_HANDYNUMMER und den HMAC-Secret. Dann klingelt Dein Telefon.

Dieser Payload testet den vollen Pfad: Webhook → DB-Insert → LiveKit-Dispatch → Sophie ruft an → Du spielst das volle Qualifizierungs-Skript durch.

Shell-Script (HMAC automatisch berechnet)

#!/bin/bash
# PERSOX Test-Lead Sender
# Voraussetzung: PERSOX_SECRET als Env-Var gesetzt (n8n Settings → Variables → PERSOX_HMAC_SECRET)
# Usage: PERSOX_SECRET="dein-secret" bash send-test-lead.sh

SECRET="${PERSOX_SECRET:-BITTE_AUS_N8N_HOLEN}"
PHONE="+49DEINE_HANDYNUMMER"  # ← ANPASSEN: z.B. +4915123456789

PAYLOAD=$(cat <<'PAYLOAD'
{
  "event_id": "f6a7b8c9-0099-0099-0099-000000TEST01",
  "event_type": "voice.call.requested",
  "occurred_at": "2026-06-03T09:00:00Z",
  "payload": {
    "application_id": "f6a7b8c9-0099-0099-0099-000000TEST01",
    "first_name": "Julian",
    "last_name": "Rockstein",
    "email": "julian@rockstein-consulting.de",
    "phone_e164": "PHONE_PLACEHOLDER",
    "job_title": "Senior DevOps Engineer m/w/d",
    "phone_script_body": "Qualifiziere diesen Bewerber professionell für die Stelle Senior DevOps Engineer in Köln / Remote. Nutze die qualification_criteria für strukturierte Fragen.",
    "qualification_criteria": [
      {
        "key": "experience_years",
        "question": "Wie viele Jahre Erfahrung als DevOps Engineer hast Du?",
        "expected": ">=5",
        "disqualify_if": "<3"
      },
      {
        "key": "skills",
        "question": "Welche Tools beherrschst Du — Kubernetes, Terraform, CI/CD pipelines?"
      },
      {
        "key": "availability",
        "question": "Wann könntest Du frühestens starten?",
        "expected": "<=3 Monate"
      },
      {
        "key": "salary_expectation",
        "question": "Was sind Deine Gehaltsvorstellungen — das Zielband liegt bei 70 bis 90k?"
      },
      {
        "key": "mobility",
        "question": "Ist Remote-Arbeit für Dich okay oder bevorzugst Du Köln vor Ort?"
      }
    ],
    "voicemail_script": "Hallo Julian, hier ist Sophie von PERSOX. Ich rufe wegen Deiner Bewerbung als Senior DevOps Engineer an. Ruf mich gerne zurück: null null vier neun — acht eins drei — fünf sieben vier drei eins null fünf. Ich freue mich auf Dein Feedback!",
    "inbound_script": "Hier ist Sophie von PERSOX — Du hast mich angerufen. Geht es um Deine Bewerbung als Senior DevOps Engineer?"
  }
}
PAYLOAD
)

# Telefonnummer einsetzen
PAYLOAD=$(echo "$PAYLOAD" | sed "s|PHONE_PLACEHOLDER|$PHONE|g")

# HMAC berechnen
SIG=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

echo "Sende Test-Lead..."
echo "Phone: $PHONE"
echo "Signature: hmac-sha256=$SIG"
echo ""

curl -s -X POST \
  "https://n8n.rockstein-consulting.de/webhook/a5e2cf90-7c7e-4476-8f19-631cd9de7616" \
  -H "Content-Type: application/json" \
  -H "x-signature: hmac-sha256=$SIG" \
  -d "$PAYLOAD" | python3 -m json.tool

echo ""
echo "Dein Telefon sollte in ~60 Sekunden klingeln."
bash · vollständiges Test-Script
Test-Isolation: Die application_id f6a7b8c9-0099-0099-0099-000000TEST01 ist bewusst als Test-ID gewählt. In Supabase filterbar via: WHERE external_id LIKE '%TEST01%'. Ein zweiter Test mit derselben ID gibt HTTP 200 + deduped:true zurück (kein neuer Anruf). Für weitere Tests einfach event_id und application_id incrementieren (TEST02, TEST03...).

07 Erwartete Ergebnisse prüfen

So verifizierst Du dass alles durchgelaufen ist.

7.1 WF 1 — Nach Webhook-Aufruf

Was prüfenWoErwartetes Ergebnis
HTTP Response curl-Output {"status":"accepted","application_id":"...","dispatch_eta":"~60s"}
Lead in DB Supabase → Tabelle public.lead → filtern nach external_id Alle 12 Felder befüllt, status=new
Cadence-Job Supabase → Tabelle public.cadence_jobs action_type=call, status=pending, attempt_number=1
n8n Execution n8n.rockstein-consulting.de → Executions → WF "01 PERSOX WF1" Execution grün, alle Nodes durchgelaufen
Anruf Dein Telefon Klingelt innerhalb ~60 Sek (Cadence-Executor-Intervall)

7.2 Nach dem Gespräch — WF 2 Post-Call

Was prüfenWoErwartetes Ergebnis
Lead-Status Supabase → public.lead status entspricht dem report_disposition-Status (qualified/disqualified/voicemail_left/...)
WF 2 Execution n8n → Executions → WF "hyz8J9zL4lVF8JRb" Post-Call-Processing durchgelaufen, Leve-Callback gesendet
Leve-Callback PERSOX Mock-Endpoint (bis Cut-Over: Mock-UI Tab 2) Leve-Schema-Event mit korrektem Status

7.3 WF 5 — Nach Status-Update

Was prüfenWoErwartetes Ergebnis
stop_contact Supabase → public.lead stop_contact=true
Cadence gecancelt Supabase → public.cadence_jobs status=cancelled für alle Jobs dieses Leads

7.4 Quick-Check Supabase

-- Supabase SQL Editor (Projekt yhsbhujgfjdaarhfpidf)

-- Test-Leads anzeigen
SELECT external_id, first_name, last_name, job_title, status,
       qualification_criteria IS NOT NULL AS has_criteria,
       stop_contact, created_at
FROM public.lead
WHERE external_id LIKE '%TEST%'
ORDER BY created_at DESC
LIMIT 10;

-- Cadence-Jobs für Test-Lead
SELECT l.external_id, c.action_type, c.status, c.attempt_number, c.scheduled_at
FROM public.cadence_jobs c
JOIN public.lead l ON c.lead_id = l.id
WHERE l.external_id LIKE '%TEST%'
ORDER BY c.created_at DESC;
SQL · Verifikation