+180 XP

ChatGPT · Wiederkehrende Arbeit mit dem OpenAI-Stack automatisieren

Das wöchentliche Wettbewerbs-Briefing, das Sie jeden Montagmorgen schreiben (fünf Blogs von Wettbewerbern überfliegen, Preisänderungen zusammenfassen, alles in eine E-Mail kopieren), kann von selbst laufen, während Sie schlafen. Der Trick: Behandeln Sie ChatGPT nicht mehr als Ort, den Sie besuchen, sondern die OpenAI API als Komponente, die Sie zeitgesteuert einplanen. In dieser Lektion wird aus einem wiederholten Chat eine Pipeline, die ohne Ihr Zutun läuft. Außerdem geht es um die Guardrails, die verhindern, dass sie teuer oder peinlich wird.

Zwei Wege zur Automatisierung: im Produkt oder über die API

Bevor Sie Code schreiben: OpenAI bietet eine No-Code-Option. In ChatGPT können Sie mit Scheduled Tasks den Assistenten einen Prompt nach festem Zeitplan ausführen und sich benachrichtigen lassen. Das eignet sich für persönliche Erinnerungen und schlanke Digests. Siehe Scheduled tasks in ChatGPT.

Scheduled Tasks leben aber in Ihrem ChatGPT-Account. Sie können nicht ohne Weiteres in ein Repo committen, in Ihr Data Warehouse schreiben oder Mails über den Transaktions-Mail-Anbieter Ihres Unternehmens versenden. Manchmal brauchen Sie echte Integration, Versionskontrolle oder einen Service-Account, der nicht an Ihr persönliches Login gebunden ist. Dann wechseln Sie zur API plus einem externen Scheduler.

Die Entscheidungsregel:

  • Eine Person, wenig Output, Benachrichtigung an mich: ChatGPT Scheduled Tasks.
  • Geteilter Output, echte Systeme, nachvollziehbare Läufe: API + cron oder CI.

Der Rest dieser Lektion behandelt den zweiten Weg.

Die Pipeline in vier Stufen

Unser Beispiel: jeden Montag um 6 Uhr aktuelle Inhalte der Wettbewerber abrufen, ein strukturiertes Briefing erstellen, es als E-Mail rendern und versenden.

Ein geplanter Job besteht aus nichts weiter als vier zusammengesteckten Stufen:

  1. Inputs sammeln (RSS-Feeds, ein paar URLs, das Briefing der Vorwoche).
  2. Das Briefing über die API generieren.
  3. Den Output gegen ein Schema validieren.
  4. Ausliefern (E-Mail, Slack, eine committete Datei).

Das Modell ist nur für Stufe 2 zuständig. Sammeln, Validieren und Ausliefern bleiben einfacher Code statt Modellaufrufe. Genau das macht die Pipeline günstig und vorhersehbar.

Warum Structured Outputs hier Pflicht sind

Im Chat lesen Sie Fließtext und machen weiter. In einer Pipeline ist die nächste Stufe Code, der das Ergebnis *parsen* muss. Liefert das Modell von Woche zu Woche leicht unterschiedliche Strukturen, bricht Ihr E-Mail-Renderer.

Nutzen Sie Structured Outputs, um das Modell zu zwingen, JSON passend zu einem von Ihnen definierten Schema zurückzugeben. Höflich fragen („bitte gib JSON zurück“) ist unzuverlässig. Bei Structured Outputs beschränkt die API die Generierung auf Ihr Schema. Lesen Sie Structured Outputs.

Den Briefing-Generator bauen

Hier der zentrale Aufruf über die Responses API, OpenAIs primäre Schnittstelle für neue Projekte. Der Block text.format legt die Antwort auf ein Schema fest.

python
import json
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

SCHEMA = {
    "type": "object",
    "properties": {
        "summary": {"type": "string"},
        "items": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "competitor": {"type": "string"},
                    "headline": {"type": "string"},
                    "why_it_matters": {"type": "string"},
                    "source_url": {"type": "string"},
                },
                "required": ["competitor", "headline", "why_it_matters", "source_url"],
                "additionalProperties": False,
            },
        },
    },
    "required": ["summary", "items"],
    "additionalProperties": False,
}

def build_brief(gathered_text: str) -> dict:
    resp = client.responses.create(
        model="gpt-5-mini",
        input=[
            {"role": "system", "content": "You are a competitive analyst. "
             "Only use facts present in the provided sources. If a claim is "
             "not supported, omit it. Never invent pricing or dates."},
            {"role": "user", "content": gathered_text},
        ],
        text={"format": {"type": "json_schema", "name": "brief",
                         "schema": SCHEMA, "strict": True}},
        max_output_tokens=2000,
    )
    return json.loads(resp.output_text)

Mit responses.create kommt das JSON als Text in resp.output_text an, Sie laden es also selbst. Wenn Sie typisierte Objekte bevorzugen, akzeptiert client.responses.parse() ein Pydantic-Modell und liefert Ihnen resp.output_parsed.

Drei bewusste Entscheidungen:

  • Ein kleines, günstiges Modell (hier gpt-5-mini, oder gpt-5-nano, wenn Ihre Evals es zulassen) kommt mit Zusammenfassungen gut zurecht. Die großen Frontier-Modelle heben Sie sich für Aufgaben mit viel Reasoning auf. Das ist Ihr größter Hebel bei den Kosten.
  • "strict": True garantiert, dass das JSON valide ist, sodass die Auslieferungsstufe ohne defensives Parsing rendern kann.
  • Der System-Prompt verbietet Erfindungen. Wiederkehrende Jobs laufen unbeaufsichtigt, ein halluzinierter Wettbewerberpreis kann also im Postfach einer Führungskraft landen, bevor es jemand merkt.

Inputs sammeln ohne riesiges Kontextfenster

Kopieren Sie nicht fünf komplette Blogs in den Prompt, um dann für Tokens zu bezahlen, die Sie nicht brauchen. Rufen Sie jeden Feed ab, behalten Sie nur Einträge, die neuer sind als Ihr letzter Lauf, und kürzen Sie jeden Artikel auf seinen Einstiegsabschnitt. Ihr gathered_text wird so zu einem kompakten, datierten Digest. Weniger Kontext heißt geringere Kosten, schnellere Läufe und weniger Gelegenheiten für das Modell, abzuschweifen.

Hier speichern Sie auch den Zustand. Schreiben Sie nach jedem erfolgreichen Lauf last_run.json, damit Sie nächste Woche nur *neue* Einträge verarbeiten. Eine Pipeline, die jede Woche dieselben Artikel erneut zusammenfasst, ist verschwenderisch und erzeugt Rauschen.

Auslieferung: erst rendern, dann senden

Halten Sie das Modell komplett aus der Auslieferung heraus. Nehmen Sie das validierte JSON, rendern Sie es mit einem Template und versenden Sie es über das, was Ihre Organisation ohnehin nutzt.

python
def render_email(brief: dict) -> str:
    lines = [f"<p>{brief['summary']}</p>", "<ul>"]
    for item in brief["items"]:
        lines.append(
            f"<li><b>{item['competitor']}:</b> {item['headline']}. "
            f"{item['why_it_matters']} "
            f"<a href='{item['source_url']}'>source</a></li>"
        )
    lines.append("</ul>")
    return "".join(lines)

Versenden Sie über das SDK Ihres Transaktions-Mail-Anbieters oder per SMTP. **Das Modell hat *strukturierte Fakten* geliefert, deterministischer Code hat das *Artefakt* erzeugt**. Muss sich das E-Mail-Layout ändern, bearbeiten Sie ein Template, keinen Prompt.

Zeitsteuerung einrichten

Jetzt machen Sie den Job wiederkehrend. Sie haben zwei saubere Optionen.

Option A: cron auf einem kleinen Server

Auf einem beliebigen dauerhaft laufenden Linux-Rechner führen Sie crontab -e aus:

bash
# Montag 06:00, Logs schreiben, Abstürze nie unbemerkt lassen
0 6 * * 1 cd /opt/briefs && /opt/briefs/.venv/bin/python run.py >> /var/log/brief.log 2>&1 || curl -s "$ALERT_WEBHOOK" -d "brief job failed"

Einfach, aber Server, Secrets-Datei und Verfügbarkeit liegen bei Ihnen.

Option B: GitHub Actions (für die meisten Teams empfohlen)

Continuous Integration (CI) bezeichnet eine gehostete Umgebung, die Ihr Skript auf einen Auslöser hin ausführt. CI-Runner sind für leichte geplante Jobs kostenlos, Secrets werden für Sie verwaltet, und jeder Lauf wird protokolliert.

yaml
name: weekly-brief
on:
  schedule:
    - cron: "0 6 * * 1"   # montags 06:00 UTC
  workflow_dispatch: {}    # ermöglicht manuelle Testläufe

jobs:
  brief:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements.txt
      - run: python run.py
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          EMAIL_API_KEY: ${{ secrets.EMAIL_API_KEY }}

workflow_dispatch ist die unterschätzte Zeile. Sie bekommen damit einen Button „Run workflow“ und können die gesamte Pipeline jederzeit testen, ohne auf Montag zu warten. Secrets liegen in den verschlüsselten Einstellungen des Repos, nie im Code.

Schedule Python Scripts with GitHub Actions

Watch on YouTube

Guardrails, die den Job sicher und günstig halten

Ein unbeaufsichtigter Job, der eine kostenpflichtige API aufruft und Ihrem Team Mails schickt, braucht Grenzen. Legen Sie sie fest, bevor Sie live gehen, nicht erst nach einer überraschenden Rechnung.

Guardrails für die Kosten

  • Setzen Sie im API-Dashboard ein Nutzungslimit, damit eine außer Kontrolle geratene Schleife Ihr Konto nicht leerräumt. Siehe production best practices.
  • Begrenzen Sie den Output mit max_output_tokens. Ein Briefing braucht keine 4.000 Tokens. Bei GPT-5-Modellen zählen Reasoning-Tokens zu diesem Limit. Lassen Sie Spielraum oder setzen Sie für einfache Zusammenfassungen reasoning={"effort": "minimal"}.
  • Verwenden Sie für diesen Job ein eigenes Projekt und einen eigenen API-Key. Mit Keys pro Projekt sehen Sie genau, was diese Pipeline kostet, und Sie können den Key separat widerrufen.
  • Wählen Sie das günstigste Modell, das Ihre Eval besteht. Testen Sie gelegentlich neu, denn günstigere Modelle werden laufend besser.

Guardrails für die Korrektheit

  • Stützen Sie das Modell ausschließlich auf die abgerufenen Quellen und verlangen Sie pro Eintrag eine source_url (das Schema erzwingt das bereits). Ein Eintrag, dessen URL nicht unter Ihren gesammelten Quellen ist, ist ein Warnsignal, und Ihr Code kann ihn verwerfen.
  • Bauen Sie zwischen Validieren und Ausliefern eine Plausibilitätsprüfung ein. Ist items leer, senden Sie „diese Woche keine nennenswerten Änderungen“ statt einer leeren Hülle. Ist die Liste verdächtig lang, markieren Sie sie zur Prüfung.

Guardrails für den Betrieb

  • Laut scheitern. Ein stiller cron-Job, der vor drei Wochen aufgehört hat zu laufen, ist schlimmer als gar kein Job. Pingen Sie bei Fehlern einen Webhook an (siehe das cron-Beispiel).
  • Wiederholen Sie vorübergehende Fehler mit Backoff. Netzwerkaussetzer und Rate Limits kommen vor, also packen Sie den API-Aufruf in einen Retry mit ein paar Versuchen.
  • Protokollieren Sie für jeden Lauf Token-Verbrauch und Kosten, auch bei Erfolg, damit Sie Abweichungen erkennen.

Wissenscheck

1. Welcher grundlegende Perspektivwechsel ist laut der Lektion nötig, um eine wiederkehrende Aufgabe mit dem OpenAI-Stack zu automatisieren?

2. Ein Team braucht ein automatisiertes Briefing, das in ein gemeinsames Repository committet, einen Service-Account ohne Bindung an ein persönliches Login nutzt und nachvollziehbare Läufe erzeugt. Welchen Ansatz empfiehlt die Lektion?

3. Warum besteht die Lektion darauf, dass in der vierstufigen Pipeline (Sammeln, Generieren, Validieren, Ausliefern) nur Stufe 2 ein Modellaufruf sein sollte?

MEHRFACHAUSWAHL

4. Wählen Sie ALLE zutreffenden Aussagen über Structured Outputs, wie sie in der Lektion beschrieben werden.

Wählen Sie alle richtigen Antworten aus.

MEHRFACHAUSWAHL

5. Wählen Sie ALLE Szenarien, in denen ChatGPT Scheduled Tasks (die No-Code-Option) laut der Lektion die passende Wahl sind.

Wählen Sie alle richtigen Antworten aus.

Skalieren: wenn ein Prompt nicht reicht

Das Design mit einem einzigen Aufruf ist der richtige Ausgangspunkt und deckt erstaunlich viel wiederkehrende Arbeit ab. Greifen Sie nur dann zu mehr Struktur, wenn die Aufgabe es verlangt.

Wann Sie Tools ergänzen

Manchmal muss der Job entscheiden, *welche* Quellen er abruft, oder Live-Systeme wie eine Pricing-API oder eine interne Suche aufrufen. Dann geben Sie dem Modell Function Calling, damit es diese Aktionen anfordern kann, und lassen Ihren Code sie ausführen. Das Modell schlägt vor, Ihr Code entscheidet. So fasst das Modell nie etwas an, das Sie nicht ausdrücklich erlaubt haben.

Wann Sie das Agents SDK nutzen

Manche Jobs haben mehrere Schritte: sammeln, entwerfen, den Entwurf kritisieren, überarbeiten, dann formatieren. Dafür orchestriert das OpenAI Agents SDK Schritte, Tools und Übergaben, sodass Sie die Steuerungsschleife nicht selbst bauen müssen. Nutzen Sie es, wenn Ihre Pipeline echte Verzweigungslogik hat. Es für die Zusammenfassung eines einzigen Feeds einzusetzen, ist Overengineering, und jeder zusätzliche Modellaufruf kostet Latenz und Geld.

Eine Anmerkung zu ChatGPT agent und Codex

Der ChatGPT agent kann innerhalb einer Sitzung browsen und agieren, um Aufgaben zu erledigen, und Codex kann Code für Sie schreiben und ausführen. Beide eignen sich hervorragend, um diese Pipeline interaktiv *zu bauen und als Prototyp zu testen*. Die Produktivversion eines wiederkehrenden Jobs sollte deterministischer Code unter Versionskontrolle sein, ausgeführt von einem Scheduler. Eine interaktive Agent-Sitzung muss beaufsichtigt werden. Bauen Sie mit dem Agent, liefern Sie mit der API aus.

Alles zusammen

Ihr run.py besteht jetzt nur noch aus den vier Stufen in Folge:

python
def main():
    state = load_state("last_run.json")
    gathered = gather_sources(feeds, since=state["last_run"])
    if not gathered.strip():
        notify("No new competitor content this week.")
        return
    brief = build_brief(gathered)
    if not brief["items"]:
        notify("No notable changes this week.")
        return
    send_email(render_email(brief))
    save_state("last_run.json", now())

if __name__ == "__main__":
    main()

Lesbar, testbar und im besten Sinne langweilig. Das Modell ist eine Zeile in der Mitte. Alles drumherum ist einfacher, debugbarer Code, und genau das wollen Sie bei etwas, das läuft, ohne dass Sie zusehen.

Das Wichtigste in Kürze

  • Überlassen Sie dem Modell nur die Generierung. Sammeln, Validieren und Ausliefern gehören in deterministischen Code, und diese Trennung macht geplante Jobs günstig und zuverlässig.
  • Erzwingen Sie Structured Outputs mit "strict": True. Bei responses.create laden Sie output_text als JSON. Nutzen Sie responses.parse, wenn Sie output_parsed möchten.
  • Planen Sie Jobs für Teams mit GitHub Actions: verwaltete Secrets, protokollierte Läufe und ein workflow_dispatch-Button zum Testen bei Bedarf. Nutzen Sie cron nur, wenn Sie den Rechner selbst kontrollieren.
  • Setzen Sie Guardrails vor dem Livegang. Das heißt: ein hartes Nutzungslimit, ein API-Key pro Projekt und das günstigste Modell, das Ihre Eval besteht (starten Sie mit gpt-5-mini oder gpt-5-nano). Ergänzen Sie ein Limit für Output-Tokens mit Spielraum für Reasoning-Tokens und einen Webhook für Fehler, damit ein toter Job nie unbemerkt bleibt.
  • Interaktiv bauen, deterministisch ausliefern. Entwickeln Sie Prototypen mit dem ChatGPT agent oder Codex, aber betreiben Sie den wiederkehrenden Job als versionierten Code. Greifen Sie nur zum Agents SDK, wenn die Aufgabe echte mehrstufige Verzweigungen hat.

Häufige Fragen

Wann sollte ich ChatGPT scheduled tasks statt der OpenAI API verwenden?

Nutzen Sie ChatGPT scheduled tasks, wenn eine einzelne Person einen einfachen wiederkehrenden Digest oder eine Erinnerung im eigenen Account braucht. Wechseln Sie zur OpenAI API mit einem externen Scheduler, sobald der Output geteilt wird, in echte Systeme wie ein Warehouse, ein Repo oder einen Anbieter für transaktionale E-Mails schreiben muss oder nachvollziehbare Runs unter einem Service-Account statt eines persönlichen Logins erfordert.

Wie strukturiere ich einen geplanten Job, der die OpenAI API aufruft?

Teilen Sie ihn in vier Stufen auf: Inputs sammeln, mit der API generieren, den Output gegen ein Schema validieren, dann ausliefern. Das Modell ist nur für die Generierung zuständig. Sammeln, Validieren und Ausliefern bleiben einfacher, deterministischer Code. Diese Trennung sorgt dafür, dass der Job Woche für Woche günstig, testbar und vorhersehbar bleibt.

Warum brauche ich Structured Outputs, statt das Modell einfach um JSON zu bitten?

Weil "bitte gib JSON zurück" unzuverlässig ist und in einer pipeline die nächste Stufe Code ist, der das Ergebnis parsen muss. Ändert sich die Struktur zwischen zwei Runs, bricht Ihr Renderer. Structured Outputs beschränkt die Generierung auf ein von Ihnen definiertes Schema. Mit "strict": true ist garantiert, dass das JSON valide ist, und der Auslieferungsschritt braucht kein defensives Parsing.

Wie plane ich ein Python-Skript mit der OpenAI API, ohne einen eigenen Server zu betreiben?

Das übernimmt GitHub Actions: Ein Workflow mit einem `on: schedule`-Cron-Trigger führt Ihr Skript auf einem gehosteten Runner aus, speichert Ihre API-Keys in den verschlüsselten Secrets des Repos und protokolliert jeden Run. Fügen Sie `workflow_dispatch: {}` hinzu, um einen manuellen "Run workflow"-Button zu erhalten, mit dem Sie die komplette pipeline bei Bedarf testen können. Ein normaler Cron auf einem Linux-Rechner funktioniert auch, dann sind aber Server, Secrets-Datei und Verfügbarkeit Ihre Sache.

Wie halte ich die Kosten eines unbeaufsichtigten OpenAI-Jobs unter Kontrolle?

Setzen Sie im API-dashboard ein Nutzungslimit, damit eine außer Kontrolle geratene Schleife das Konto nicht leerräumen kann, und geben Sie dem Job ein eigenes Projekt und einen eigenen API-Key. So sehen Sie genau, was er kostet, und können ihn separat sperren. Wählen Sie das günstigste Modell, das Ihre Eval besteht, etwa gpt-5-mini oder gpt-5-nano für Zusammenfassungen. Begrenzen Sie `max_output_tokens`. Beachten Sie dabei, dass bei GPT-5-Modellen die Reasoning-Tokens auf dieses Limit angerechnet werden. Kürzen Sie außerdem die Inputs, statt ganze Artikel einzufügen.

Sollte ich das OpenAI Agents SDK für einen wiederkehrenden Zusammenfassungs-Job verwenden?

Nein, nicht für einen einzelnen Zusammenfassungsschritt. Ein einziger API-Aufruf mit Schema deckt erstaunlich viel wiederkehrende Arbeit ab, und jeder zusätzliche Modellaufruf kostet Latenz und Geld. Das Agents SDK lohnt sich, wenn die pipeline echte Verzweigungen hat: sammeln, entwerfen, kritisieren, überarbeiten, formatieren. Nutzen Sie den ChatGPT agent oder Codex für den Prototyp und liefern Sie den wiederkehrenden Job dann als versionierten, deterministischen Code aus.

Was Sie aus dieser Lektion umsetzen

Diese Maßnahmen sind im Playbook der Rolle zusammengefasst.

  • Geplante Tasks als vollständige, eigenständige Prompts schreiben, die das Verhalten in ruhigen Wochen festlegen
  • Harte Abrechnungslimits setzen, mit separaten API-Keys pro Umgebung
  • Lassen Sie das Modell nur die Generierung übernehmen; Sammeln, Validieren und Ausliefern erledigt der Code
Vollständiges Action Playbook ansehen →