Was macht CounterCall?
Pak Yanto hat sich den Vormittag freigenommen, vierzig Minuten zum Samsat-Schalter gefahren und wurde abgewiesen, weil seine Fotokopie im Folio- statt A4-Format war. Er verlor einen Tageslohn und wusste immer noch nicht, was ihm morgen sonst noch fehlen würde.
Öffentliche Dienststellen veröffentlichen Anforderungslisten, die unvollständig, veraltet oder am Schalter stillschweigend widerlegt sind. Die einzig verlässliche Quelle ist die Telefonleitung des Amtes, und die ist besetzt, mit IVR-Hürden versehen und wird erst beim vierten Versuch beantwortet. Also rufen die Leute nicht an. Sie reisen an, stellen sich an und werden wegen eines einzigen Dokuments abgewiesen.
Dieser Skill führt stattdessen den Anruf durch und gibt eine Checkliste zurück, die der Nutzer als Screenshot speichern und mitnehmen kann.
Er passt gut zu CALL-Es Design: seltene, persönliche, risikoreiche Telefonate gegen eine Nummer, die ein Mensch sonst den ganzen Vormittag lang immer wieder wählen müsste.
Vorbereitung
Dieser Skill tätigt einen echten Anruf bei einer echten öffentlichen Stelle. Bestätigen Sie mit dem Nutzer:
- um welches Verfahren es geht, in den eigenen Worten der Behörde
- um welche Behörde es sich handelt, und die Telefonnummer im E.164-Format, von der veröffentlichten Seite der Behörde
- dass jetzt ein Anruf gewünscht wird
Leiten Sie niemals eine Telefonnummer ab. Nicht aus einem Verzeichnis, nicht von einer ähnlichen Behörde, nicht durch Erraten einer Ländervorwahl. Eine Nummer kommt nur dann in den Ablauf, wenn ein Mensch sie von der veröffentlichten Seite der Behörde abgelesen hat. Die falsche Nummer anzurufen bedeutet, dass ein automatisierter Anrufer bei einem Fremden landet – das Schlimmste, was dieser Skill tun kann.
Sicherheitsgrenzen
Dieser Skill sammelt nur Schalteranforderungen.
- Er reicht keinen Antrag ein, bucht keinen Termin, zahlt keine Gebühr und verpflichtet den Nutzer zu nichts. Er fragt und berichtet.
- Er gibt keine Rechts- oder Einwanderungsberatung. Schlägt ein Sachbearbeiter einen alternativen Weg vor, berichten Sie dies wörtlich als Aussage des Sachbearbeiters, niemals als Empfehlung.
- Die mündliche Antwort eines Sachbearbeiters ist informativ, nicht rechtsverbindlich, und jedes ausgegebene Ergebnis weist darauf hin. Anforderungen ändern sich, und einzelne Schalter wenden Ermessen an.
- Er stellt zu Beginn des Anrufs klar, dass es sich um einen automatisierten Assistenten handelt und warum er anruft. Lehnt die Person das Gespräch ab, bedankt er sich und beendet den Anruf. Er besteht nicht darauf, fragt nicht erneut und ruft am selben Tag nicht zurück.
- Ein Anruf pro Behörde, pro Verfahren, pro Tag. Diese Leitungen werden von Menschen mit einer Warteschlange vor sich bedient. Der Idempotenz-Key erzwingt dies; entfernen Sie ihn nicht.
- Ist der Sachbearbeiter unsicher, sagt das Ergebnis „unsicher“. Es füllt nie eine Lücke mit typischen Annahmen und stellt nie eine vage Aussage als Tatsache dar. Eine Person könnte auf der Grundlage dieser Antwort quer durch die Stadt reisen.
- Er ruft nur während der veröffentlichten Öffnungszeiten an. Eine öffentliche Leitung, die um 22:00 Uhr klingelt, ist kein Datenpunkt, sondern eine Belästigung.
Lesen Sie references/safety.md, bevor Sie diesen Skill an eine neue Einrichtung anpassen. Manche Angerufenen sind grundsätzlich kein geeignetes Ziel für einen automatischen Anrufer.
Was unterscheidet das von einem Transkript
Die meisten Anruf-Skills geben Prosa zurück und überlassen die Interpretation dem Leser. Dieser gibt ein festgelegtes, validiertes Objekt zurück und weigert sich, etwas anderes auszugeben.
Das result_schema des Goals setzt additionalProperties: false und schränkt vier Felder auf Aufzählungen ein – payment_method, appointment_required, originals_or_copies und clerk_certainty, jedes mit einem Wert für „der Sachbearbeiter wusste es nicht“. Wenn der Anruf anders geformt zurückkommt, wird das Ergebnis unter Quarantäne gestellt und nicht ausgegeben. Eine halb geparste Checkliste ist schlimmer als keine Checkliste, weil der Nutzer danach handelt.
Der vollständige Vertrag steht in references/result-contract.md.
Arbeitsablauf
1. Anfrage sammeln
Erforderlich: der Verfahrensname, der Behördenname, die Telefonnummer der Behörde im E.164-Format und die veröffentlichte Quell-URL, von der die Nummer stammt.
Validieren Sie die Nummer, bevor irgendetwas anderes passiert. E.164 ist ein Plus, eine von Null verschiedene Ländervorwahlziffer und dann 7 bis 14 weitere Ziffern: ^\+[1-9]\d{7,14}$. Lehnen Sie alles andere ab und fragen Sie den Nutzer. Raten Sie niemals eine Ländervorwahl. Eine Nummer im lokalen Format, die den Wähler erreicht, ist der Weg, wie die falsche Person angerufen wird.
Führen Sie scripts/preflight.mjs aus, um die Nummer und den Vertrag zu prüfen, ohne zu wählen.
2. Prüfen, ob der veröffentlichte Vertrag abgewichen ist
Vor jedem Durchlauf lesen Sie die Live-Goal-Schnittstelle und vergleichen sie mit dem Vertrag, für den dieser Skill geschrieben wurde.
import { diffContract, publishedRunSpec } from './scripts/_lib.mjs';
const goal = await client.goals.get(GOAL_ID);
const drift = diffContract(PINNED_CONTRACT, publishedRunSpec(goal));
if (drift.length) throw new ContractDrift(drift); // Verweigere die Wahl
Verwenden Sie den Helfer publishedRunSpec(goal), nicht direkt goal.published_run_spec. Das Wire-Format und die Dokumentation schreiben es als published_run_spec.result_schema; das TypeScript SDK camelCased es zu publishedRunSpec.resultSchema. Wenn Sie nur den dokumentierten Namen gegen den TS-Client lesen, erhalten Sie undefined statt eines Fehlers – die Sicherung schließt dann auf „keine veröffentlichte Spezifikation“ und verweigert jeden einzelnen Anruf, während es aussieht, als würde es funktionieren. Der Helfer liest beide Schreibweisen. Das hat uns einen Tag gekostet; es ist in FEEDBACK.md im Repository-Stammverzeichnis festgehalten.
Die CALL-E-Dokumentation empfiehlt diesen Vergleich vor dem Bereitstellen einer Variablenänderung. Ihn bei jedem Durchlauf durchzuführen, kostet einen API-Aufruf und verwandelt einen stillen Fehler in eine laute Verweigerung. Mit einem veralteten Schema eine echte Person anzurufen, erzeugt ein Ergebnis, das gut aussieht und leise falsch ist.
3. Einen Anruf tätigen
goals.run mit einem Idempotency-Key, der auf Behörde, Verfahren und Datum beschränkt ist, sodass ein erneuter Versuch niemals eine öffentliche Leitung doppelt anruft:
countercall:{office}:{procedure}:{yyyy-mm-dd}:v1
4. Auf ein Ergebnis oder einen Fehler warten
goals.waitForResult hat eine einzige Abschlussregel: anhalten, wenn entweder result oder error nicht null ist. Ein abgeschlossener Anruf kann kurzzeitig beide null zurückgeben, während CALL-E das strukturierte Ergebnis parst – behandeln Sie dieses Fenster also nicht als Fehler.
5. Ausgeben oder ehrlich scheitern
Alle acht veröffentlichten GoalRunError-Codes führen zu einem eigenen Ergebnis. Die folgende Menge ist die, die scripts/render.mjs implementiert – halten Sie sie synchron, wenn CALL-E einen Code hinzufügt.
| Ergebnis | Was der Nutzer sieht |
|---|---|
| gültiges Ergebnis | die Checkliste mit der wörtlichen Aussage des Sachbearbeiters und der Quell-URL |
no_answer | „Die Leitung hat nicht geantwortet“. Keine Checkliste |
declined | „Das Amt hat es abgelehnt, einen automatischen Anrufer zu beantworten“. Keine Checkliste |
result_invalid | Der Anruf wurde abgeschlossen, aber die Antwort entsprach nicht dem Vertrag. Unter Quarantäne |
result_unavailable | Der Anruf wurde abgeschlossen, aber es gab keine strukturierte Antwort. Keine Checkliste |
result_failed | Die Antwort konnte nicht zu einer Checkliste verarbeitet werden. Keine Checkliste |
timed_out | „Keine verwertbare Antwort“ vor Ablauf der Frist. Keine Checkliste |
call_failed | Der Anruf konnte nicht abgeschlossen werden. Keine Checkliste |
canceled | Abgebrochen, bevor eine Antwort vorlag. Keine Checkliste |
Kein Zweig gibt eine unvollständige Checkliste aus. Ausgearbeitete Beispiele für jeden Fall finden Sie in references/examples.md.
Ausführen
scripts/call.mjs ist standardmäßig ein Trockenlauf. Es gibt die genaue Anfrage aus, die es senden würde, und tätigt keinen Anruf. Zum Wählen ist ein explizites --live erforderlich:
# Trockenlauf – gibt die Anfrage aus, die es senden würde, wählt nichts, benötigt keine Anmeldedaten
node scripts/call.mjs --office <id> --procedure "<procedure>"
# Tatsächliches Klingeln
node scripts/call.mjs --office <id> --procedure "<procedure>" --live
Ein Skill, der standardmäßig wählt, ist ein Skill, der versehentlich wählt.
data/offices.json wird mit maskierter Telefonnummer ausgeliefert (+62XXXXXXXXXX), sodass der eingetragene Eintrag nicht wählen kann und jeder Befehl dagegen mit Exit-Code 3 und REFUSING TO DIAL endet. Das ist beabsichtigt: Eine Nummer kommt nur dann in die Datei, wenn ein Mensch sie von der veröffentlichten Seite der Behörde abgelesen und source_url und source_checked aufgezeichnet hat. Fügen Sie vor dem Ausführen von irgendetwas Ihren eigenen Eintrag hinzu.
Um die Ausgabe des Trockenlaufs sofort zu sehen, enthält die Testvorrichtung eine gültige fiktive Nummer:
node scripts/call.mjs --offices ../../test/fixtures/offices.test.json \
--office fixture-sourced --procedure "perpanjangan paspor"
Wann dies nicht verwendet werden sollte
- Notfälle. Dies ist eine Anforderungsabfrage mit einer Latenz von mehreren Minuten. Es ist kein Weg, um dringend jemanden zu erreichen.
- Behörden mit einer veröffentlichten, zuverlässigen, aktuellen Anforderungsseite. Wenn die Website korrekt ist, lesen Sie die Website. Der Anruf ist nur gerechtfertigt, wenn die veröffentlichte Antwort bekanntermaßen unvollständig ist.
- Jede Einrichtung, die darum gebeten hat, nicht von automatischen Systemen angerufen zu werden, oder in der lokale Gesetze automatische Anrufe einschränken. Überprüfen Sie dies, bevor Sie eine Behörde hinzufügen.
- Hochvolumige Abfragen. Eine Behörde pro Verfahren pro Tag ist die Obergrenze, konstruktionsbedingt. Wenn Sie Massenanfragen benötigen, brauchen Sie eine Datenweitergabevereinbarung, kein Telefon.
- Alles, bei dem ein Fehler billig ist. Der Wert hier liegt in den Kosten einer verschwendeten Reise. Wenn der Nutzer einfach hingehen und es herausfinden kann, lassen Sie ihn.
Ehrliche Einschränkungen
- Die Abdeckung beschränkt sich auf Behörden in der Seed-Datei, jede mit einer veröffentlichten Quell-URL.
- Die Antwortraten bei öffentlichen Dienstleitungen variieren je nach Behörde und Tageszeit, und ein großer Teil der Anrufe wird nicht beantwortet. Diese Unzuverlässigkeit ist der Grund, warum dieser Skill existiert, und sie wird berichtet statt versteckt.
- Das Ergebnis ist die Antwort eines Sachbearbeiters an einem Tag. Es ist ein Anhaltspunkt, keine Garantie.