GitHub Issue Management mit KI: Claude-gestütztes Triage, das funktioniert
Maintainer shippen keine Software am Dienstagmorgen. Sie triagieren. Sie lesen ein neues Issue, prüfen, ob es ein Duplikat von etwas ist, das vor drei Wochen eingereicht wurde, entscheiden, ob es ein Bug oder eine Frage ist, wählen eine Priorität, vergeben zwei oder drei Labels und schreiben manchmal einen höflichen Kommentar, der nach einem Repro fragt. Dann machen sie das beim nächsten Issue in der Queue genauso. Die Arbeit ist reiner Admin und frisst auf jedem aktiven Repo jede Woche echte Stunden.
Dieser Walkthrough zeigt, wie sich der Großteil davon durch einen Claude-Agenten ersetzen lässt, der das Issue liest, Repo-Kontext zieht und per Tool Use ein striktes Triage-Payload zurückgibt, auf das Ihr Code reagieren kann. Sie nehmen ein funktionierendes Mental Model mit, ein Tool-Schema, das Sie direkt in Ihren Service einfügen können, und eine Meinung dazu, ob Sie selbst bauen oder direkt zu einer gehosteten Lösung greifen sollten.
Primäres Keyword auf dem Tisch: GitHub Issue Management mit KI. Sekundär: KI-Label-Automatisierung für GitHub, GitHub-Issues automatisieren, Issue-Klassifikation, GitHub-Bot mit Claude. Ich verwende sie dort, wo sie hingehören — und nirgendwo sonst.
Das Problem, das Maintainer nur zu gut kennen
Issue-Triage sieht isoliert betrachtet billig aus. Ein Issue, zwei Minuten. Zehn Issues am Tag, das sind zwanzig Minuten. Auf einem populären OSS-Repo oder einem aktiven internen Monorepo liegt die Zahl eher bei sechzig bis neunzig Minuten fragmentierter Aufmerksamkeit. Fragmentiert, weil jedes Issue Sie aus dem herausreißt, woran Sie eigentlich gebaut haben.
Die Arbeit selbst ist Pattern Matching. Ist das ein Bug oder ein Feature Request. Ist es ein Duplikat. Welche Komponente ist betroffen. Ist es p1 oder p3. Brauchen wir ein Repro. Genau diese Klassifikationsaufgaben können Sprachmodelle gut, und die Structured-Output-Patterns aus Claude API Tool Use machen den Output zuverlässig genug, um zu handeln, ohne dass für jeden Schritt ein Mensch dazwischen sitzt.
Was KI an Issue-Triage ändert
Ein gut gestalteter Claude-Agent liest den Issue-Body, scannt die Kommentare, zieht die letzten 50 Issues als Kontext, prüft verlinkte PRs und berücksichtigt das Repo-README plus die bestehende Label-Taxonomie. In einem einzigen Call gibt er Kategorie, Priorität, vorgeschlagene Labels, einen Duplikat-Kandidaten, einen Kommentar-Entwurf und einen Confidence-Score zurück. Ihr Code entscheidet anhand von Schwellenwerten, was damit passiert.
Der Unterschied zu klassischen ML-Label-Klassifikatoren: Sie trainieren nichts. Sie schreiben einen Prompt, zeigen auf ein Tool-Schema und lassen das Modell über freien Kontext schließen. Der Prompt ist das Modell. Wenn Sie das Verhalten ändern wollen, editieren Sie Englisch, keine Retraining-Pipelines.
Das ist dasselbe Agent-Pattern, das im Production AI Agent Architecture Guide detailliert beschrieben wird. Issue-Triage ist der sauberste erste Agent zum Ausliefern, weil die Inputs begrenzt sind, die Outputs strukturiert sind und der Schaden eines Fehlgriffs gering bleibt, solange man auf Confidence gated.
Drei Automatisierungsstufen zur Auswahl
Wählen Sie die, die zu Ihrem Risikoappetit passt.
Stufe 1: Suggest-Only. Claude entwirft auf jedes neue Issue einen Triage-Kommentar. Der Maintainer liest, editiert, vergibt Labels manuell. Sie bekommen den Kontext vorgekaut, ohne die Kontrolle abzugeben. Hier sollte jeder anfangen.
Stufe 2: Auto-Label, manuelles Schließen. Claude vergibt Labels oberhalb einer Confidence-Schwelle (0,8 funktioniert als Default). Duplikat-Schließungen bleiben bei Menschen, weil das falsche Schließen eines fremden Issues ein schlechter Look ist. Kommentar-Entwürfe werden als Vorschläge gepostet.
Stufe 3: Voll automatisiert. Labels, Verlinkungen zu Duplikaten und Schließungen laufen alle auf Confidence-Schwellen. Vorbehalten für interne Repos, wo der Blast Radius klein ist und Observability vorhanden ist.
Die meisten Teams leben in Produktion auf Stufe 2. Ich würde empfehlen, mindestens einen Monat dort zu bleiben, bevor man überhaupt über Stufe 3 nachdenkt.
Der minimale Stack
Nichts Aufwendiges. Die Bausteine:
- GitHub-Webhook auf
issues.openedundissues.reopened, empfangen von einer GitHub App - Ein kleiner Node- oder Python-Service, oder ein n8n-Workflow, wenn Sie Low-Code bevorzugen
- Claude API mit Tool Use für strukturierten Output
- GitHub REST API für das Setzen von Labels, Posten von Kommentaren, Verlinken von Duplikaten
GitHub App vor PAT — jedes Mal. Sie bekommen Repo-scoped Installation Tokens, keine User-Impersonation und einen sauberen Permission-Audit. Die Webhook-Signature-Verifikation gibt es gratis dazu.
Walkthrough: Kontext → Claude → Aktion
Der Ablauf in fünf Schritten.
Schritt 1: GitHub App und Webhook
Registrieren Sie eine GitHub App, abonnieren Sie Issues-Events, vergeben Sie Issues: read & write und Contents: read. Installieren Sie sie auf dem Repo. Die App sendet bei jedem passenden Event einen signierten POST an Ihren Receiver. Verifizieren Sie den X-Hub-Signature-256-Header, bevor Sie irgendetwas anderes tun.
Schritt 2: Kontext-Sammlung
Bevor Sie Claude aufrufen, ziehen Sie:
- Den Issue-Body und -Titel
- Die Kommentare zum Issue (deckeln Sie bei den letzten 20, um günstig zu bleiben)
- Die letzten 50 Issues des Repos (nur Titel, plus Nummer und State)
- Das Repo-README, CONTRIBUTING.md und die vollständige Liste der bestehenden Labels
Dieser Kontextblock ist das, was den Triage-Call intelligent macht. Ohne ihn rät Claude an Ihrer Label-Taxonomie herum. Mit ihm lernt das Modell Ihre Konventionen in-context.
Schritt 3: Claude-Call mit Tool Use
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const triageTool = {
name: "triage_issue",
description: "Classify a GitHub issue and recommend triage actions.",
input_schema: {
type: "object" as const,
properties: {
category: {
type: "string",
enum: ["bug", "feature", "question", "duplicate"],
},
priority: {
type: "string",
enum: ["p0", "p1", "p2", "p3"],
},
labels_to_add: {
type: "array",
items: { type: "string" },
description: "Labels from the repo's existing taxonomy only.",
},
is_duplicate_of: {
type: "number",
description: "Issue number if duplicate, else null.",
},
draft_comment: {
type: "string",
description: "A polite, edit-ready triage comment.",
},
confidence: {
type: "number",
description: "0.0 to 1.0 confidence in this classification.",
},
},
required: ["category", "priority", "confidence"],
},
};
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
tools: [triageTool],
tool_choice: { type: "tool", name: "triage_issue" },
system: [
{
type: "text",
text:
"You are a triage assistant for a GitHub repo. Use the tool to classify. " +
"Be conservative on duplicates. Only use labels that exist in the provided taxonomy.",
},
{
type: "text",
text: repoContextBlock,
cache_control: { type: "ephemeral" },
},
],
messages: [
{
role: "user",
content: `New issue #${issue.number}: ${issue.title}\n\n${issue.body}\n\nRecent comments:\n${commentsBlock}\n\nLast 50 issues:\n${recentIssuesBlock}`,
},
],
});
Beachten Sie das cache_control auf dem Repo-Kontextblock. README, CONTRIBUTING und Label-Liste ändern sich zwischen Issues nicht. Cachen. Beim zweiten Call innerhalb des 5-Minuten-Fensters zahlen Sie für diesen Chunk grob ein Zehntel des Preises. Die vollständigen Caching-Regeln stehen im Claude API Prompt Caching Post.
Schritt 4: Auf den strukturierten Response reagieren
Ziehen Sie den Tool-Input aus dem Response heraus. Handeln Sie mit Schwellenwerten.
const toolUse = response.content.find((b) => b.type === "tool_use");
const triage = toolUse.input as TriageOutput;
if (triage.confidence >= 0.8) {
await octokit.rest.issues.addLabels({
owner, repo,
issue_number: issue.number,
labels: triage.labels_to_add,
});
}
if (triage.is_duplicate_of && triage.confidence >= 0.9) {
await octokit.rest.issues.createComment({
owner, repo,
issue_number: issue.number,
body: `This looks like a duplicate of #${triage.is_duplicate_of}. Closing, reopen if I got this wrong.`,
});
}
if (triage.draft_comment) {
await octokit.rest.issues.createComment({
owner, repo,
issue_number: issue.number,
body: triage.draft_comment,
});
}
Schritt 5: Edge Cases
Private Repos brauchen die App mit Read-Scope auf Contents installiert. GitHub-API-Rate-Limits liegen bei 5.000 Requests pro Stunde pro Installation, was für Triage-Volumen reichlich ist. Claude-Rate-Limits hängen von Ihrem Tier ab. Große Issues mit langen Threads: paginieren Sie den Kommentar-Endpoint und kürzen Sie die ältesten Kommentare, bevor sie Ihr Token-Budget sprengen.
Das triage_issue-Tool-Schema
Das Schema von oben in einem Block, fertig zum Einfügen.
{
"name": "triage_issue",
"description": "Classify a GitHub issue and recommend triage actions.",
"input_schema": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["bug", "feature", "question", "duplicate"]},
"priority": {"type": "string", "enum": ["p0", "p1", "p2", "p3"]},
"labels_to_add": {"type": "array", "items": {"type": "string"}},
"is_duplicate_of": {"type": "number", "description": "Issue number if duplicate, else null"},
"draft_comment": {"type": "string"},
"confidence": {"type": "number", "description": "0.0 to 1.0"}
},
"required": ["category", "priority", "confidence"]
}
}
Erzwungenes Tool Use (tool_choice: {type: "tool", name: "triage_issue"}) räumt Mehrdeutigkeit aus. Das Modell kann nicht in Prosa abdriften. Sie bekommen entweder einen validen Tool-Call oder einen API-Fehler — beides deutlich leichter zu behandeln als Freitext zu parsen.
Strategien zur Duplikat-Erkennung
Drei Optionen, die Kosten gegen Recall abwägen.
Claude-basiert. Geben Sie die Titel der letzten 50 bis 100 Issues in den Prompt und lassen Sie das Modell Kandidaten erkennen. Einfach, keine extra Infrastruktur, funktioniert gut bis zu ein paar Hundert historischen Issues. Verpasst danach zunehmend ältere Dupes.
Embedding-basiert. Embedden Sie jedes Issue bei Erstellung, speichern Sie die Vektoren in einer DB und führen Sie auf jedes neue Issue eine Ähnlichkeitssuche aus. Die Top 3 gehen zu Claude zur Bestätigung. Skaliert auf Zehntausende Issues. Braucht einen Vector Store und ein Embedding-Modell.
Hybrid. Embeddings grenzen auf 20 Kandidaten ein, Claude bestätigt, welcher (falls überhaupt) ein echtes Duplikat ist. Bester Recall, immer noch günstig. Das ist es, was ich auf einem Repo mit über tausend Lifetime-Issues ausliefern würde.
Auto-Labeling ohne False Positives
Schwellenwert-Arbeit ist der Punkt, an dem Triage-Bots ihren Lohn verdienen — oder nervig werden.
Starten Sie bei Confidence 0,8 für Auto-Apply, 0,6 für Suggest-Only. Lassen Sie die erste Woche in Stufe 1 (Suggest-Only) laufen, loggen Sie jede Entscheidung des Modells, dann schauen Sie sich die Outputs an. Tunen Sie den System-Prompt anhand der Fehler, die Sie sehen. Typische Fixes: “Niemals ein Label vergeben, das nicht in der gelieferten Liste steht”, “Bug-Reports ohne Repro als needs-repro behandeln, nicht als bug”, “Fragen gehen nach discussion, nicht question, wenn das Repo discussion hat”.
Versuchen Sie nicht, die Schwellenwerte einzustellen, bevor Sie 50 echte Outputs angeschaut haben. Sie werden auf Rauschen fitten.
Kosten pro Issue
Mit Sonnet-4.6-Pricing und einem realistischen Kontext-Payload:
- Input: rund 5.000 Tokens (Repo-Kontext + Issue + letzte Issues)
- Output: rund 500 Tokens (der Tool-Call)
- Uncached: grob 0,02 USD pro Issue
- Mit Prompt Caching auf dem Repo-Kontextblock: grob 0,005 USD pro Issue bei Warm-Calls
Rechnen Sie es auf Ihr Volumen hoch. Ein Repo mit 500 neuen Issues pro Monat landet bei 2,50 bis 10 USD API-Kosten. Vergleichen Sie das mit 30 Sekunden bis 2 Minuten Maintainer-Zeit pro Issue zu Ihrem voll geladenen Stundensatz. Das Verhältnis ist nicht knapp.
Production Hardening
Die Liste der Fehler, die ich Ihnen gerne ersparen würde.
- Maximal ein Bot-Kommentar pro Issue. Tracken Sie, ob der Bot schon kommentiert hat, und kurzschließen. Nichts zerstört Vertrauen in einen Bot schneller als Doppelkommentare.
- CODEOWNERS respektieren. Wenn ein File-Path-Pattern einem Team gehört, routen Sie die Prioritäts-Zuweisung an das Team, statt zu raten.
- Kein Auto-Close in Woche eins. Lassen Sie es im Suggest-Modus laufen. Gaten Sie Schließungen hinter manuellem Review, bis Sie eine Confidence-Kalibrierung haben, der Sie vertrauen.
- Jede Entscheidung loggen. Speichern Sie den Tool-Call-Input, die Confidence und die ausgeführten Aktionen. Sie werden das brauchen, wenn Sie Schwellen tunen — und wenn jemand fragt, warum sein Issue als
needs-reprogelabelt wurde. - Sich selbst rate-limiten. Eine Welle von 200 Issues durch einen Spam-Bot sollte nicht 200 Claude-Calls auslösen. Deduplizieren Sie nach Autor und ziehen Sie eine Obergrenze pro Repo.
Selbst bauen oder Off-the-Shelf einsetzen
Bauen Sie selbst, wenn Sie drei oder mehr Repos mit konsistentem Triage-Bedarf haben, Ops-Kapazität für einen eigenen Service mitbringen und bereit sind, Prompt-Drift zu babysitten, wenn sich Ihre Label-Taxonomie ändert. Bauen Sie, wenn der Agent in interne Systeme (Slack, PagerDuty, Ihr eigenes CRM) integriert werden soll, die kein Off-the-Shelf-Tool anbindet.
Lassen Sie den Eigenbau und nehmen Sie eine Open-Source-Implementierung, wenn Sie das in dieser Woche live haben wollen, wenn Sie nicht einen Monat Tuning-Zeit haben, oder wenn Sie schlicht den Triage-Output und den Review-Loop wollen, ohne ihn von Null zu schreiben. FixClaw ist genau diese Architektur auf GitHub, mit dem Hardening bereits eingebaut. Selbes Mental Model — forken und laufen lassen.
Eine tiefere Aufschlüsselung der Architektur, die FixClaw mitbringt, steht im FixClaw AI GitHub Triage Guide.
Erweiterungen, die sich lohnen
Sobald der Basis-Triage-Agent läuft, sind die offensichtlichen nächsten Schritte:
- Reviewer automatisch zuweisen für Issues mit bestimmten Komponenten-Labels, über ein Mapping von Label zu GitHub-Team.
- Wöchentlicher Triage-Digest in den Maintainer-Slack: neue Issues, stale Issues, ungelabelte Issues, geflaggte aber nicht bearbeitete Duplikate.
- Stale-Issue-Handling mit einem respektvollen Kommentar (“seit 90 Tagen keine Aktivität, wird geschlossen, jederzeit wieder öffnen”). Günstige Wins für Backlog-Hygiene.
- Verwandte PRs verlinken beim Issue-Open: nach offenen PRs suchen, deren Body Issue-Keywords erwähnt, und verlinken.
Die meisten sind kleine Erweiterungen desselben Tool-Use-Patterns. Tool hinzufügen, System-Prompt-Instruction ergänzen, ausliefern.
Wenn Sie die Triage-Fähigkeit selbst als wiederverwendbaren Server exponieren wollen, den Claude Code, Cursor oder jeder MCP-Client on demand aufrufen kann, schauen Sie sich den TypeScript-MCP-Server-Guide an. Und wenn Sie den Agent-Loop in Claude Code bauen statt als eigenständigen Service, deckt der Claude Code SDK Agents Post die Harness-Seite ab.
Wochenend-Roadmap
Ein realistischer Pfad von Null bis Shipped.
Samstag. GitHub App registrieren. Webhook-Receiver hochziehen (Hono, Express, Fastify, was auch immer). Signaturen verifizieren. Erste Version des Tool-Schemas schreiben. Test-Issue-Payload hardcoden und einen Claude-Call hinbekommen, der validen Tool-Input zurückgibt.
Sonntag. Die Kontext-Sammler verdrahten (README, CONTRIBUTING, letzte Issues, Labels). Den Receiver irgendwo mit öffentlicher URL deployen (Cloudflare Workers, Railway, ein Hetzner-VPS mit Tunnel). Die App auf einem Repo installieren und das erste echte Issue im Suggest-Modus durchlaufen sehen.
Woche 1. In Stufe 1 (Suggest-Only) laufen lassen. Jede Entscheidung loggen. Outputs täglich anschauen. System-Prompt anhand der gesehenen Fehler tunen.
Woche 2. Auf Stufe 2 wechseln. Auto-Label bei 0,8 Confidence einschalten. Duplikat-Schließungen manuell halten. Die Duplikat-Erkennungs-Strategie anhand des bisher Gelernten verfeinern.
Nach zwei Wochenenden und zwei Wochen Tuning haben Sie einen funktionierenden Triage-Agenten auf einem Repo. Das Ausrollen auf das zweite Repo ist eine Config-Änderung. Das Ausrollen auf das zehnte ist dieselbe Config-Änderung.
Der Bau ist nicht schwer. Das Tuning ist die Arbeit. Wenn dieser Monat Tuning der Teil ist, für den Sie keine Zeit haben, ist das der Moment, eine gehostete Lösung zu nehmen, statt den Betrieb selbst zu schultern.
Weiterführende Beiträge
- Claude API Tool Use Guide für das Structured-Output-Pattern, auf dem dieser Agent aufbaut.
- Production AI Agent Architecture für das breitere Pattern, von dem dieser Triage-Agent eine Instanz ist.
- FixClaw AI GitHub Triage, falls Sie den Eigenbau überspringen und die gehostete Version laufen lassen wollen.