Skip to content

GitHub Issue Resolver AI Agent with Haystack

In this notebook, we'll create a GitHub Issue Resolver Agent with Anthropic Claude 4 Sonnet. Given an issue URL, the agent will:

  • Fetch and parse the issue description and comments
  • Identify the relevant repository, directories, and files
  • Retrieve and process file content
  • Determine the next steps for resolution and post them as a comment

For this, we'll use the new Agent component. Agent is a Haystack component that implements a tool-calling functionality with provider-agnostic chat model support. We can use Agent either as a standalone component or within a pipeline.

Here's what our GitHub Issue Resolver Pipeline looks like:

issue_resolver_pipeline.png

Development Environment Setup

%%bash

pip install anthropic-haystack github-haystack
Hidden output

Add API Credentials

Anthropic and Github

import os
from getpass import getpass

os.environ["ANTHROPIC_API_KEY"] = getpass("Anthropic Key: ")
os.environ["GITHUB_TOKEN"] = getpass("Github Token: ")

Initialize a GitHubIssueViewer component

The GitHubIssueViewer component takes a GitHub issue URL and returns a list of Haystack documents. The first document contains the main issue content, while the subsequent documents contain the issue comments.

Initialize the component and test it with issue -> https://github.com/deepset-ai/haystack/issues/8903

Notice the data each Document object holds: content, url...

from haystack_integrations.components.connectors.github import GitHubIssueViewer
from haystack.utils.auth import Secret

issue_viewer = GitHubIssueViewer(github_token=Secret.from_env_var("GITHUB_TOKEN"))
issue_comments = issue_viewer.run(url="https://github.com/deepset-ai/haystack/issues/8903")
issue_comments

Initialize the Issue Builder Component

This component will get the Documents and render them in a prompt. Use ChatPromptBuilder to render the prompt in Jinja syntax

from haystack.components.builders import ChatPromptBuilder
from haystack.dataclasses import ChatMessage

issue_template = """
Issue from: {{ url }}
{% for document in documents %}
    {% if loop.index == 1 %}
        **Title: {{ document.meta.title }}**
    {% endif %}
    <issue-comment>
        {{document.content}}
    </issue-comment>
{% endfor %}
"""

issue_builder = ChatPromptBuilder(template=[ChatMessage.from_user(issue_template)],required_variables="*" )

issue_builder.run(documents=issue_comments["documents"], url="https://github.com/deepset-ai/haystack/issues/8903")
Hidden output

Initialize a GitHubRepoViewer Tool

This tool retrieves content from a GitHub repository based on a given repo and path:

  • If the path points to a directory, it returns a list of Documents—one per item—where each document contains the item's name (file or directory) along with full path and metadata in Document.meta.
  • If the path points to a file, it returns a single Document containing the file content, with full path and metadata in Document.meta.
  • If an error occurs, it returns a single Document with the error message, and Document.meta includes type="error".
from haystack_integrations.tools.github import GitHubRepoViewerTool
from haystack.utils.auth import Secret

repo_viewer_tool = GitHubRepoViewerTool(github_token=Secret.from_env_var("GITHUB_TOKEN"))

Initialize a GitHubIssueCommenter Tool from a function