Sammlung von Informationen zum Herbst-Recruiting (秋招信息搜集)
Ein Skill zur Sammlung von Informationen über das chinesische Campus-Recruiting (Herbst-Recruiting), Praktika und die Übernahme von Praktika. Zuerst werden die Präferenzen des Nutzers ermittelt, dann werden Stellen aus öffentlichen Quellen entdeckt, vorrangig auf den offiziellen Unternehmensseiten verifiziert und schließlich mit deterministischen Skripten abgeglichen, Duplikate entfernt, Änderungen erkannt und Fristen identifiziert. Die Stellenliste wird direkt in den aktuellen Chat zurückgegeben.
Laufzeitumgebung (Open Source, portabel)
Dieser Skill ist für die Open-Source-Verteilung ausgelegt. Jeder kann ihn auf seinen eigenen Rechner klonen und installieren. Daher müssen folgende Bedingungen erfüllt sein:
-
Plattformunabhängig: Alle Skripte verwenden reine Python 3.8+ Standardbibliotheken und laufen unter Windows, macOS und Linux; es werden keine absoluten Pfade fest codiert und keine betriebssystemspezifischen Befehle wie
osascriptoderlaunchdverwendet. -
Modell-/Clientunabhängig: Die Stellensuche erfolgt ausschließlich über die integrierte Hintergrund-Websuche und die Fähigkeit zum Lesen von Webseiten des Host-Clients. Es werden keine zusätzlichen Tools installiert, kein Benutzerbrowser gesteuert und keine zusätzlichen Kosten verursacht.
-
Nur zwei Pfade:
- Der Client verfügt über eine Hintergrundsuche / Webseitenlesefunktion (Trae, Claude und andere gängige AI-Clients haben diese standardmäßig) → die Stellen werden direkt im Hintergrund gesammelt, der Nutzer muss nichts weiter tun.
- Der Client hat keinerlei Netzwerkfähigkeit → Der Nutzer wird mit dem unten stehenden Hinweis informiert und der Vorgang wird gestoppt. Es werden unter keinen Umständen Stellen, Unternehmen, Links oder Fristen erfunden.
Fester Hinweis, wenn keine Netzwerkverbindung verfügbar ist:
Der aktuelle Client hat keine verfügbare Websuche-Funktion. Ich kann keine Stelleninformationen in Echtzeit abrufen. Bitte führen Sie diesen Skill in einem AI-Client aus, der die Websuche unterstützt.
-
Unabhängig davon, welcher Pfad zu Stellen führt, wird das Ergebnis einheitlich in
runtime/inbox/jobs-input.jsongeschrieben. Die nachfolgende Verarbeitung ist identisch.
Konfigurationsgrenzen
Vor Beginn vollständig lesen:
- configuration.md: Grenzen der benutzerkonfigurierbaren Einstellungen, Projekteinstellungen und des Ausführungsstatus.
- data-contract.md: Ein- und Ausgabefelder der Stellen.
- source-strategy.md: Quellenpriorität, Entdeckungs- und Verifizierungsprozess.
Der Benutzer darf config/project.json nicht ändern. Benutzereinstellungen werden nur in runtime/user-preferences.json geschrieben; Programmstatus wird nur in runtime/state/ geschrieben.
Schritt 0: Initialisierung
Zunächst ausführen:
SKILL_DIR=$(cd "$(dirname "SKILL.md")" && pwd)
python3 "$SKILL_DIR/scripts/bootstrap.py"
runtime/user-preferences.json lesen. Wenn onboarded nicht true ist, werden nur die folgenden fünf noch nicht geklärten Punkte abgefragt:
- Abschlussjahrgang;
- Zielposition;
- Zielstadt;
- Nur Campus-Recruiting, oder auch Praktika und Übernahme von Praktika;
- Welche Art von Unternehmen (mit
discovery.company_type_options:Große Internetkonzerne/KI-Einhörner & große Modelle/Nischen- & Branchenunternehmen/Alle), und ob es zusätzliche Präferenzen für bestimmte Unternehmen/Branchen gibt.
Die Antworten in runtime/user-preferences.json schreiben:
- Ein leeres Array für die Stadt bedeutet "Ganz China".
- Der Unternehmenstyp (Punkt 5) wird verwendet, um in Schritt 1 eine "Warteschlange von Unternehmen" zu generieren und zu bestimmen, wer zuerst durchsucht wird. Die konkrete Liste wird zur Laufzeit durch eine Echtzeitsuche ermittelt, nicht fest codiert. Der Nutzer muss nicht selbst wissen, welche Unternehmen es gibt.
- Präferenzen für Unternehmen und Branchen dienen standardmäßig nur zur Sortierung/Bonuspunkte, nicht zur harten Filterung.
- Der Nutzer wird nicht aufgefordert, eine Liste von Schlüsselwörtern einzugeben. Der Agent generiert
role_keywordsbasierend auf den natürlichen Sprachzielen; z.B. sollte "AI-Produkt" gängige Bezeichnungen wie AI-Anwendungsproduktmanager, AI-Großmodellproduktmanager, AI-Agent-Produktmanager, AIGC-Produktmanager und Produktmanager (AI-Richtung) abdecken. - Nach Abschluss wird
onboardedauftruegesetzt und dem Nutzer eine Zusammenfassung der Konfiguration gegeben.
Bei der Frage nach dem Unternehmenstyp einen neutralen Tonfall wie bei den anderen Fragen beibehalten: dem Nutzer erklären, dass die konkrete Unternehmensliste vom Assistenten zur Laufzeit durch eine Echtzeitsuche ermittelt wird. Der Nutzer muss nur eine grobe Kategorie auswählen, nicht die Unternehmen selbst auflisten.
Die Frage nach dem Aktivieren von "Update-Benachrichtigungen" wird erst nach der ersten Ausgabe gestellt (siehe Schritt 5). Im Initialisierungsschritt nicht danach fragen.
Schritt 1: Stellen entdecken (gestaffelt + Streaming-Auslieferung)
config/project.json (insbesondere den discovery-Abschnitt) und references/source-strategy.md lesen.
Kernprinzip: Der Nutzer wartet nicht darauf, dass "alles durchsucht ist", sondern auf die "nächste Stelle, auf die er sich bewerben kann". Daher immer nach und nach liefern, nicht erst alles berechnen und dann ausliefern. Siehe source-strategy.md unter "Gestaffelte Streaming-Erkennung".
Die Erkennung erfolgt in zwei Schritten:
1a. Zuerst die "Unternehmenswarteschlange" entdecken (Echtzeit, einmal mehrere abdecken)
- Der Unternehmenstyp wird vom Nutzer in Schritt 0 ausgewählt (
Große Internetkonzerne/KI-Einhörner & große Modelle/Nischen- & Branchenunternehmen/Alle); die Liste ist nicht fest codiert. - Aggregationsseiten, Rankings, Hochschul-Jobbörsen und ähnliche
Platform-Übersichtsseiten, die "mit einem Mal Dutzende von Unternehmen" liefern können, verwenden. In Echtzeit nach einer Charge von "Unternehmensnamen + Stellenhinweisen" suchen, die den Kriterien des Nutzers (Stadt + Position + Unternehmenstyp) entsprechen. Daraus eine geordnete Warteschlange erstellen (z.B.: Bytedance → Alibaba → Tencent → …). discovery.employer_anchorskann verwendet werden, um bekannte Unternehmen zuerst erscheinen zu lassen;employer_anchorsdient nur als Sortieranker und gelegentliches Auffangnetz. Die tatsächliche Liste basiert auf dieser Suche.- Diese Hinweise selbst können als "vorläufige Version (zu verifizieren)" zuerst an den Nutzer zurückgegeben werden, ohne Zeit zu verlieren.
1b. Dann die Warteschlange "Unternehmen für Unternehmen" verifizieren und vervollständigen (Streaming, nach jedem Unternehmen ausliefern)
- In der Reihenfolge der Warteschlange arbeiten, nicht mehr als
discovery.stream.max_concurrent_lookupsUnternehmen gleichzeitig. - Innerhalb eines Unternehmens zuerst die "neuest veröffentlichten / offenen" Stellen (
in_hiring_first) nehmen, die älteren hinten anstellen. - Nach jedem Unternehmen die Stellen dieses Unternehmens zum aktuellen Chat hinzufügen (
deliver_per_company), nicht warten, bis die gesamte Warteschlange abgearbeitet ist. - Erste Welle:
first_batch_max_companiesUnternehmen (Standard: 3) ausliefern, damit der Nutzer innerhalb weniger Sekunden etwas sieht. - Maximal
max_companies_per_runUnternehmen pro Durchlauf, maximalmax_per_companyStellen pro Unternehmen, um Kontrollverlust zu vermeiden. - Wenn nach einer Charge
ask_before_long_tailwahr ist, den Nutzer fragen: "Soll ich weiter nach KI-Einhörnern / Nischen usw. suchen?". Nur bei "Weiter" ausweiten, bei "Genug" sofort stoppen und die bisherigen Ergebnisse zusammenfassen. - Die noch nicht durchsuchten Unternehmen in der Warteschlange für den nächsten Durchlauf aufheben, nicht verwerfen.
Kandidatenstellen müssen data-contract.md entsprechen: source_tier kann nur official, official_wechat oder platform sein. Aggregations-/Weiterleitungsseiten und Medienlinks werden vom Skript direkt abgelehnt und können nur als "Hinweise" dienen. Die Ergebnisse der schrittweisen Streaming-Ausgabe werden einheitlich in (mehrfach anhängbar) geschrieben:
runtime/inbox/jobs-input.json
Es ist verboten, Veröffentlichungs- oder Fristen zu erraten; wenn die Seite diese nicht explizit angibt, unknown schreiben. Falls eine Quelle fehlschlägt oder leer ist, dies wahrheitsgemäß protokollieren und nicht wiederholt versuchen, Zugriffsbeschränkungen zu umgehen.
Schritt 2: Offizielle Verifizierung
Für Stellen, die aus nicht-offiziellen Quellen entdeckt wurden, vorrangig die offizielle Unternehmensseite mit den detaillierten Stelleninformationen suchen:
- Offizielle Detailseite gefunden: Diese als Hauptquelle setzen, die ursprüngliche Aggregationsseite in
alternate_sourcesschreiben. - Nur den offiziellen Unternehmens-WeChat-Account gefunden: Quellenstufe
official_wechatschreiben. - Keine offizielle Seite gefunden: Die tatsächliche Quellenstufe beibehalten, nicht als offiziell tarnen.
- Die offizielle Seite zeigt explizit an, dass die Stelle geschlossen, offline oder die Rekrutierung eingestellt ist:
source_statusaufclosedsetzen. - Die Seite erlaubt noch Bewerbungen:
source_statusaufopensetzen. - Kann nicht beurteilt werden:
unknownschreiben.
Pro Durchlauf maximal 5 neue Unternehmen intensiv verifizieren, um Kosten außer Kontrolle zu geraten.
Schritt 3: Abgleich, Deduplizierung und Änderungserkennung
Ausführen:
python3 "$SKILL_DIR/scripts/radar.py" run \
--input "$SKILL_DIR/runtime/inbox/jobs-input.json" \
--preferences "$SKILL_DIR/runtime/user-preferences.json" \
--project-config "$SKILL_DIR/config/project.json" \
--state-dir "$SKILL_DIR/runtime/state"
Das Programm muss:
- Nach Jahrgang, Position, Stadt und Recruiting-Typ abgleichen.
- Präferenzen für Unternehmen und Branchen geben nur Bonuspunkte.
- Gleiches Unternehmen, gleiche Position, gleiche Stadt, gleicher Jahrgang, gleicher Recruiting-Typ: Quelle übergreifend deduplizieren.
- Offizielle Quellen bevorzugen, schwächere Quellen als Backup-Belege behalten.
- Stabile Felder vergleichen, um
new,changed,seenzu identifizieren. - Die konkreten
changed_fieldsausgeben. - Wenn das Fristdatum vor dem Ausführungsdatum liegt oder die offizielle Seite die Stelle explizit als geschlossen markiert, als
expiredkennzeichnen. - Abgelaufene Stellen archivieren, nicht in die Auslieferung aufnehmen.
fetched_atnicht zur Änderungsbewertung heranziehen.
Schritt 4: Direkte Rückgabe an den Chat
Das Skript gibt standardmäßig eine prägnante Chat-Liste aus, die nur neue, geänderte und noch nicht abgelaufene Stellen enthält. Die vollständige Ausgabe des Skripts direkt in den aktuellen Chat zurückgeben. Dem Nutzer nicht nur den Dateipfad mitteilen und ihn nicht auffordern, einen Bericht zu öffnen.
Interne Statusdateien:
runtime/state/
├── jobs.json
├── jobs.csv
├── seen.json
├── expired.json
├── rejected.json
├── daily/YYYY-MM-DD.md
└── outbox/YYYY-MM-DD.md
Die Chat-Liste muss enthalten:
- Unternehmen
- Stellenbezeichnung
- Stadt
- Recruiting-Typ
- Gehalt/Leistungen
- Veröffentlichungsdatum
- Frist
- Stelle-Schlüsselwörter (wichtige Schlüsselwörter aus den Anforderungen der Stelle)
- Stellen-Highlights
- Bewerbungslink
- Informationsquelle
- Status und geänderte Felder
daily/ ist ein interner Prüf-Snapshot; outbox/ ist eine interne Kopie der Chat-Liste. Der Nutzer muss diese Dateien nicht öffnen. seen, expired und doppelte Stellen derselben Charge dürfen nicht wiederholt zurückgegeben werden.
Schritt 5: Nach Abschluss der Ergebnisverarbeitung fragen, ob Update-Benachrichtigungen aktiviert werden sollen
Nach dem ersten Durchlauf und der Auslieferung der Stellenliste den Nutzer fragen: „Darf ich Sie benachrichtigen, wenn neue Stellen hinzukommen oder sich bestehende ändern?“
- Nutzer lehnt ab:
schedule.notify_on_updateauffalsesetzen (Standardwert), beenden, nichts weiter tun. - Nutzer stimmt zu:
schedule.notify_on_updateauftruesetzen und gemäß Schritt 6 die nachfolgenden Heartbeat-Läufe planen.
Der Nutzer kann seine Entscheidung jederzeit ändern: Mit der Aussage „Ich möchte keine Benachrichtigungen mehr“ wird notify_on_update auf false zurückgesetzt, und es werden auch bei neuen/geänderten Stellen keine aktiven Benachrichtigungen mehr gesendet. Mit „Benachrichtigungen wieder aktivieren“ wird es wieder auf true gesetzt. Es handelt sich um einen wiederholbaren Schalter, keine einmalige Einrichtung.
Schritt 6: Heartbeat-Benachrichtigungen (nur wenn notify_on_update true ist)
Die Bedeutung von Heartbeat ist einfach: In regelmäßigen Abständen den Agenten diesen Skill erneut ausführen lassen (erneutes Sammeln → Deduplizieren → Vergleich mit dem historischen Status).
- Wenn bei diesem Lauf „neue“ oder „geänderte“ Stellen gefunden werden, wird diese Liste an den aktuellen Dialog gesendet.
- Wenn es keine neuen oder geänderten Stellen gibt, wird nichts gesendet, Ruhe bewahrt, der Nutzer wird nicht gestört.
Es ist ausschließlich auf „erneutes Ausführen + Vergleich mit dem historischen Status” angewiesen. Es werden keine System-Popups, E-Mails oder Webhooks verwendet. Wer das „erneute Ausführen“ auslöst, ist zweigeteilt, von allgemein bis erweitert:
6.1 Standardebene (für alle nutzbar, keine Konfiguration, plattform- und modellunabhängig)
Jeder, der diesen Skill klont, verwendet standardmäßig diese Ebene, ohne auf irgendeinen Timer angewiesen zu sein:
- Sitzungsbeginn = Inkrementelle Aktualisierung (der universelle „Tägliche Sammler“): Wenn dieser Skill in einer Sitzung aktiviert wird,
notify_on_updatewahr ist und seit dem letzten Lauf ein Tag vergangen ist, führt der Agent automatisch mit der integrierten Websuche des Host-Clients eine erneute Sammlung der vom Nutzer verfolgten Unternehmen (z. B. Bytedance, Alibaba) durch → Deduplizierung → Vergleich mit dem historischen Status → nur neue/geänderte Stellen an den Nutzer senden; bei keinen Aktualisierungen Ruhe bewahren. Der Nutzer muss nicht jedes Mal explizit „Überprüfen“ sagen und muss keine Hintergrundbefehle konfigurieren. Da der Nutzer seinen AI-Client täglich öffnet, findet die netzwerkabhängige Aufgabe „Neue Stellen entdecken“ auf natürliche Weise in der ersten täglichen Konversation statt – dies ist die einzige Sammelmethode, die für alle GitHub-Nutzer null Konfiguration, null Kosten und geräteunabhängig ist. - Benutzerinitiierte Auslösung: Der Nutzer kann jederzeit sagen „Überprüfe / Schau nach, ob es Neuigkeiten gibt“, woraufhin sofort ein erneuter Lauf gestartet wird.
- Der tägliche Einstiegspunkt
--heartbeathinzugefügt. Keine Ausgabe bei keinen Aktualisierungen, nur bei Aktualisierungen wird die Liste zurückgegeben:
python3 "$SKILL_DIR/scripts/run_daily.py" \
--project-config "$SKILL_DIR/config/project.json" --heartbeat
Wenn notify_on_update true ist, fügt run_daily.py automatisch einen Heartbeat hinzu; das manuelle Hinzufügen des Parameters ist nicht erforderlich.
6.2 Optionale erweiterte Ebene: Geplante Ausführung durch Host/System („Tägliche automatische Push-Benachrichtigung zu einer festgelegten Uhrzeit“)
Wenn der Nutzer explizit eine „tägliche automatische Push-Benachrichtigung zu einer festgelegten Uhrzeit“ wünscht, wird dies nach der folgenden Priorität umgesetzt, wobei die Kosten ehrlich dargelegt werden:
- Bevorzugt die planmäßige oder Erinnerungsfunktion des Host-Agenten/Clients verwenden (falls vorhanden), damit dieser den Skill zur geplanten Zeit erneut ausführt. Dies ist am einfachsten und erfordert keine Systemeingriffe.
- Wenn der Host keine Planungsfähigkeit hat, kann das plattformunabhängige Skript scripts/schedule_task.py verwendet werden, um eine native Betriebssystem-Planungsaufgabe (macOS launchd / Linux cron / Windows Task Scheduler) zu registrieren. Es generiert die Konfiguration basierend auf dem System des Nutzers und der gewählten Zeit. Es werden keine Pfade fest codiert und keine Geräte des Betreuers gebunden:
# Zuerst Vorschau (Standard: print, ändert das System nicht, sicher):
python3 "$SKILL_DIR/scripts/schedule_task.py" --action print --time 08:00
# Nach Bestätigung durch den Nutzer echt installieren (ändert den lokalen Rechner):
python3 "$SKILL_DIR/scripts/schedule_task.py" --action install --time 08:00
# Anzeigen / Deinstallieren:
python3 "$SKILL_DIR/scripts/schedule_task.py" --action status
python3 "$SKILL_DIR/scripts/schedule_task.py" --action remove
Vor der Installation muss zuerst eine print-Vorschau gemacht und die Zustimmung des Nutzers eingeholt werden; nach Zustimmung die vom Nutzer gewählte Zeit in schedule.time schreiben und schedule.enabled auf true setzen.
Dem Nutzer müssen zwei reale Einschränkungen klar kommuniziert werden (nicht verschweigen, nicht zu „24/7 Cloud“ aufbauschen):
- Der Computer muss eingeschaltet sein: Die Systemplanungsaufgabe wird nur ausgelöst, wenn dieser Computer zur geplanten Zeit eingeschaltet ist; bei ausgeschaltetem oder ruhendem Computer wird sie nicht ausgeführt und nicht nachgeholt.
- Die Planungsaufgabe selbst führt keine „erneute Websuche nach Stellen“ durch:
run_daily.pyverarbeitet standardmäßig nur die bereits vorhandenen Eingaben erneut (Deduplizierung, Änderungen, Ablaufarchivierung). Daher sollte dercollector.commandinconfig/project.jsonstandardmäßig leer sein und leer bleiben (siehecommand_notefür dieses Feld). Dies ist kein Fehler: Die eigentliche Entdeckung neuer Stellen wird durch die „automatische Websuche bei Sitzungsbeginn“ in 6.1 übernommen, die für alle Nutzer null Konfiguration und null Kosten bietet. Es gibt keinen „allgemeinen, kostenlosen, für alle GitHub-Nutzer ausführbaren“ Hintergrund-Netzwerkbefehl. Daher solltecollector.commandnicht verteilt werden, um der Planungsaufgabe die Suche nach neuen Stellen zu ermöglichen.
- Wenn der Host weder eine Planung unterstützt noch der Nutzer Systemaufgaben verwenden möchte, auf die Standardebene zurückfallen: Dem Nutzer mitteilen: „Wenn Sie mich das nächste Mal verwenden, wird automatisch eine inkrementelle Aktualisierung durchgeführt, oder Sie können jederzeit ‚Überprüfen‘ sagen.“ Es wird auf keinen Fall eine native Betriebssystem-Planungsaufgabe als Cloud-Push-Benachrichtigung getarnt.
Abnahme
bash "$SKILL_DIR/scripts/validate_skill.sh"
Die Abnahme muss Folgendes nachweisen:
- Erster Lauf erzeugt neue Stellen.
- Erneuter Lauf mit denselben Eingaben führt keine Duplikat-Pushs durch.
- Quellübergreifende doppelte Stellen behalten nur die stärkere Quelle.
- Bei geänderten Feldern werden
changedund die konkreten geänderten Felder ausgegeben. - Erneuter Lauf mit geänderter Eingabe wird zu
seen. - Explizit abgelaufene und datumsmäßig abgelaufene Stellen gehen in
expired. - Abgelaufene Stellen erscheinen nicht in der Chat-Liste.
- Stadt, Recruiting-Typ, Veröffentlichungsdatum, Frist, Quelle und Highlights erscheinen alle in der Chat-Liste.
- Standardbefehl gibt direkt die Chat-Liste aus, JSON wird nur für automatisierte Tests verwendet.
Sicherheit und Authentizität
- Nur auf öffentliche Seiten zugreifen; keine Login-geschützten, internen oder nicht-öffentlichen Schnittstellen scrapen.
- Keine Cookies, Kontopasswörter oder private Informationen von Recruitern speichern.
- Keine Captchas, Anti-Scraping-Mechanismen oder Zugriffsbeschränkungen umgehen.
- Unbekannte Daten als
unknownschreiben, nicht raten. - Interner Status und Chat-Liste behalten Quellenname, -stufe, -link und Abrufzeitpunkt bei.
- Vor dem Absenden einer Bewerbung sollte die Stelle dennoch auf der offiziellen Unternehmensseite überprüft werden.