Webhook icon
If icon
CreateCollection icon
Request icon
Query icon
OutputValues icon
Switch icon
Comment icon
SlackIncomingWebhook icon
ChatCompletion icon
Log icon
Upsert icon

GitHub Issue Triage and Duplicate Detection with Qdrant

Triage GitHub issues with OpenAI embeddings and Qdrant vector search to detect duplicates, auto-label categories, and notify Slack.

Categories
AI

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

Automate GitHub issue triage, semantic duplicate detection, and category labeling using OpenAI, Qdrant vector search, and Kestra orchestration. In active open-source and enterprise repositories, maintainers frequently spend hours manually reading incoming issues, flagging duplicates, and assigning taxonomy labels. Traditional keyword searches often fail because users describe identical problems using entirely different terminology.

This blueprint reacts to newly opened GitHub issues via a webhook, converts the title and body into dense vector embeddings with OpenAI, and queries a Qdrant collection for existing semantically similar issues. When candidate duplicates cross a configurable cosine similarity threshold, the workflow tags the issue with a possible-duplicate label, posts a polite comment linking to prior matching issues with confidence scores, and alerts the maintainer Slack channel. If no duplicates are found, the flow runs an OpenAI classification model to auto-label the issue with standard taxonomy categories (e.g., bug, feature, question, documentation) and indexes the new issue into Qdrant for future matching.

How it works

  1. github_issue_webhook receives GitHub issue event webhooks authenticated by a shared secret key configured in the webhook URL.
  2. gate_issue_event (io.kestra.plugin.core.flow.If) gates execution to only process opened actions authored by human users (user.type != 'Bot') with non-empty titles. All other actions and bot activities are safely logged and skipped.
  3. create_collection_if_missing (io.kestra.plugin.qdrant.CreateCollection) idempotently ensures the target Qdrant collection exists with 1536-dimensional cosine vector configuration.
  4. create_embedding (io.kestra.plugin.core.http.Request) invokes the OpenAI Embeddings API (text-embedding-3-small) to convert the issue title and body into a high-dimensional vector.
  5. search_similar_issues (io.kestra.plugin.qdrant.Query) searches Qdrant for nearest neighbor vectors above similarity_threshold (default 0.82) using fetchType: FETCH.
  6. filter_matches (io.kestra.plugin.core.output.OutputValues) excludes the current issue number from the search candidates to prevent self-matching.
  7. route_triage_decision (io.kestra.plugin.core.flow.Switch) inspects candidate counts:
    • Duplicate candidates found: add_duplicate_label applies the possible-duplicate label, comment_duplicate_matches posts a markdown comment listing matching issue URLs and similarity scores, and notify_slack_duplicate posts an alert to the triage Slack channel.
    • No duplicates found: classify_issue (io.kestra.plugin.openai.ChatCompletion) classifies the issue into standard categories using structured JSON output, validates the label against allowed_labels, and applies the validated label to the issue via apply_category_label.
  8. upsert_issue_vector (io.kestra.plugin.qdrant.Upsert) indexes the issue number, embedding vector, title, and URL into Qdrant so subsequent incoming issues can match against it. Setting the point ID to the issue number guarantees idempotent upserts on redelivered webhooks.

What you get

  • Automated semantic duplicate detection that catches similar issues even when described with different phrasing.
  • Automated comment generation linking new issues directly to historical issues with similarity percentages.
  • Automated category classification (bug, feature, question, docs) for unique issues using structured JSON schema.
  • Zero human overhead for repetitive initial triage, freeing maintainers to focus on code review and bug fixes.
  • Real-time Slack notifications dispatched only when duplicate issues require maintainer attention.

Who it's for

  • Open Source Maintainers managing high-traffic GitHub repositories.
  • Developer Relations and Engineering Support teams triaging public issue backlogs.
  • Platform and SRE teams standardizing incident and bug intake across distributed microservices.

Why orchestrate this with Kestra

Building duplicate detection with custom webhooks or ad hoc scripts introduces infrastructure maintenance, unhandled rate limits, lost webhook retries, and brittle vector store connections.

Orchestrating this with Kestra provides an event-driven webhook endpoint, declarative retries across GitHub, OpenAI, and Qdrant APIs, conditional routing with Switch and If tasks, and end-to-end execution lineage without managing dedicated server daemons.

Prerequisites

  • A GitHub repository with administrative access to configure webhooks and personal access tokens.
  • An OpenAI API key with access to text-embedding-3-small and gpt-4o-mini.
  • A Qdrant cluster (Qdrant Cloud or self-hosted gRPC endpoint) reachable from the Kestra instance.
  • A Slack Incoming Webhook URL for triage channel alerts.

Secrets

  • GITHUB_WEBHOOK_KEY: Secret key securing the Kestra webhook trigger endpoint against unauthorized HTTP calls.
  • GITHUB_TOKEN: GitHub Personal Access Token (classic or fine-grained) with issues:write permissions.
  • OPENAI_API_KEY: OpenAI API key used for generating vector embeddings and structured chat classification.
  • QDRANT_HOST: Hostname or IP address of the Qdrant gRPC service endpoint (default port 6334).
  • QDRANT_API_KEY: API key used to authenticate with the Qdrant vector database.
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook URL used to dispatch duplicate detection notifications.

Quick start

  1. Configure the six required secrets in your Kestra namespace: GITHUB_WEBHOOK_KEY, GITHUB_TOKEN, OPENAI_API_KEY, QDRANT_HOST, QDRANT_API_KEY, and SLACK_WEBHOOK_URL.
  2. Copy the generated Webhook URL from the Kestra UI under the github_issue_webhook trigger (e.g., https://<kestra-host>/api/v1/executions/webhook/company.team/github-issue-triage-and-duplicate-detection-qdrant/<your-key>).
  3. In your GitHub repository settings under Webhooks, add a webhook with Content type application/json and select the Issues event. Note that GitHub signs payloads with HMAC while Kestra authenticates incoming calls via the secret webhook key embedded in the URL path.
  4. Open a test issue in the repository and verify automated duplicate matching or categorization in Kestra's execution graph.

How to extend

  • Pull Request triage: Extend the trigger to handle pull_request events to cross-reference incoming PRs against open bug issues.
  • Cross-encoder reranking: Add a Cohere or local cross-encoder reranking task before commenting to further filter semantic false positives.
  • Auto-closing resolved duplicates: Automatically close duplicate issues and link the master issue when similarity exceeds 0.95.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.