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.
How to Summarise GitHub with CrewAI
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
Get API keyExample
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)
What you get back
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.