---
title: "Summarise GitHub with CrewAI using EnConvert Distill"
description: "Summarise GitHub content inside a CrewAI agent using EnConvert Distill, returning a clean summary from repos, issues, and PRs in one call without parsing logic"
canonical: "https://www.enconvert.com/solutions/summarise-github-with-crewai-using-enconvert-distill"
locale: "en"
---

# How to Summarise GitHub with CrewAI

A CrewAI agent that reads GitHub content needs a summary, not a page dump. Fetching a repository, issue, or pull request directly returns sidebar navigation, contributor panels, reaction counts, and rendering markup that bury the content the agent actually needs. The GitHub REST API avoids the HTML but returns raw markdown or JSON, and you still have to write the parsing and summarisation logic before any of it is usable. EnConvert’s Distill endpoint takes a GitHub URL and returns a clean summary of the repository, README, issue thread, or pull request in one API call, ready to pass into a CrewAI tool.

## Example

```python
import os

import requests
from crewai import Agent, Crew, Task
from crewai.tools import BaseTool
from pydantic import BaseModel, Field

ENCONVERT_API_KEY = os.environ["ENCONVERT_API_KEY"]
GITHUB_URL = os.environ["GITHUB_URL"]  # a public GitHub repo, issue, or pull request URL
# CrewAI's default LLM reads OPENAI_API_KEY from the environment


class GitHubUrlInput(BaseModel):
    url: str = Field(description="The GitHub repository, issue, or pull request URL")


class GitHubDistillTool(BaseTool):
    name: str = "GitHub content summariser"
    description: str = (
        "Summarises a GitHub repository, issue, or pull request URL "
        "into clean prose using EnConvert Distill."
    )
    args_schema: type[BaseModel] = GitHubUrlInput

    def _run(self, url: str) -> str:
        # Step 1: Distill the GitHub page into a summary
        response = requests.post(
            "https://api.enconvert.com/v2/distill",
            headers={
                "X-API-Key": ENCONVERT_API_KEY,
                "Content-Type": "application/json",
            },
            json={
                "urls": [url],
                "schema": {
                    "summary": (
                        "a clear summary of the page. For a repository: its "
                        "purpose and README. For an issue: what is raised, its "
                        "status, and any proposed fix. For a pull request: "
                        "what it changes and its review status"
                    ),
                },
            },
            timeout=120,
        )
        response.raise_for_status()

        # Distill reports failures per URL, so check the item, not just the HTTP status
        item = response.json()["results"][0]
        summary = (item.get("data") or {}).get("summary")
        if item.get("error") or not summary:
            raise RuntimeError(
                f"Distill failed for {url}: {item.get('error') or item.get('warnings')}"
            )
        return summary


github_tool = GitHubDistillTool()

# Step 2: Give the tool to a CrewAI agent
analyst = Agent(
    role="GitHub content analyst",
    goal="Summarise GitHub repositories, issues, and pull requests into usable context",
    backstory="You read GitHub content and produce clean summaries for downstream tasks.",
    tools=[github_tool],
    verbose=True,
)

task = Task(
    description=(
        f"Summarise the GitHub page at {GITHUB_URL} "
        "and report what it covers and whether a fix has been proposed."
    ),
    expected_output="A short summary of the page, its current status, and any proposed fix.",
    agent=analyst,
)

# Step 3: Run the crew
crew = Crew(agents=[analyst], tasks=[task])
result = crew.kickoff()
print(result.raw)
```

## Output

Distill returns the repository description, README content, or issue thread as clean prose, with contributor metadata, labels, and navigation chrome stripped before the response comes back. Fetching raw GitHub HTML produces bloated output with sidebar and header markup embedded in the text. The GitHub REST API avoids the HTML but returns unformatted markdown or JSON that still requires a separate summarisation step before an agent can use it.

## Get started

[Get free API key — 500 ops per month, no card required.](https://www.enconvert.com/auth?mode=signup)

## Related solutions

- [How to Ingest Markdown Files into LlamaIndex with EnConvert](https://www.enconvert.com/solutions/ingest-markdown-files-into-llamaindex-with-enconvert.md)
- [How to Ingest Web Pages into Vertex AI with EnConvert](https://www.enconvert.com/solutions/ingest-web-pages-into-vertex-ai-with-enconvert.md)
- [How to Ingest Markdown into OpenAI File Search with EnConvert](https://www.enconvert.com/solutions/ingest-markdown-into-openai-file-search-enconvert.md)
- [How to Ingest HTML Files into LlamaIndex with EnConvert](https://www.enconvert.com/solutions/ingest-html-files-into-llamaindex-with-enconvert.md)
- [Best Browserless Alternative for Document Parsing](https://www.enconvert.com/solutions/browserless-alternative-for-document-parsing-enconvert.md)
- [How to Ingest DOCX into CrewAI with EnConvert](https://www.enconvert.com/solutions/ingest-docx-into-crewai-with-enconvert.md)
