An AutoGen agent that reads Jira content needs a summary of the issue, not the page template around it. Jira pages carry navigation headers, sidebar panels, activity feeds, watcher lists, and linked issue widgets, and all of it lands in the output when you fetch a URL directly. The Jira REST API avoids the markup but requires authentication and project-level access that you often do not have, and it returns nested JSON across several endpoints that you still have to assemble and summarise before an agent can use it. EnConvert’s Distill endpoint takes a Jira URL and returns a clean summary of the issue or project content in one API call, ready to pass into an AutoGen tool.
How to Summarise Jira with AutoGen
How to summarise Jira content inside an AutoGen agent with EnConvert Distill, returning a clean LLM-ready summary of any issue or project page in one call
Get API keyExample
python
import asyncio
import os
from typing import Annotated
import requests
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
ENCONVERT_API_KEY = os.environ["ENCONVERT_API_KEY"]
JIRA_URL = os.environ["JIRA_URL"] # a publicly viewable Jira issue, Epic, or board URL
# Step 1: Wrap Distill as an AutoGen tool the agent can call on demand
# AutoGen reads the signature, annotations, and docstring to build the tool schema
def summarise_jira_page(
url: Annotated[str, "Jira issue, Epic, board, or backlog URL to summarise"],
) -> str:
"""Fetch a Jira page and return a clean summary of its content."""
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 thorough summary of the Jira page, including its title, "
"current status, description, acceptance criteria, and the "
"key points from the comment thread"
),
},
},
timeout=120,
)
response.raise_for_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
# Step 2: Create an agent that can call the tool
model_client = OpenAIChatCompletionClient(
model="gpt-4.1",
api_key=os.environ["OPENAI_API_KEY"],
)
agent = AssistantAgent(
name="jira_assistant",
model_client=model_client,
tools=[summarise_jira_page],
system_message=(
"You help engineering teams understand Jira work. "
"Use the summarise_jira_page tool to read a Jira URL before answering."
),
# Send the tool result back to the model so it writes the final answer
reflect_on_tool_use=True,
)
# Step 3: Ask the agent about the Jira page
# agent.run is async, so it must be awaited inside an event loop
async def main() -> None:
result = await agent.run(
task=(
f"Summarise {JIRA_URL} "
"and list the acceptance criteria and current status."
)
)
print(result.messages[-1].content)
await model_client.close()
asyncio.run(main())
What you get back
Distill returns the issue title and description, acceptance criteria, and comment thread as clean prose, with navigation panels, watcher lists, activity feeds, and linked issue widgets stripped before the response comes back. Fetching the raw HTML instead returns Jira’s full page template with Atlassian UI chrome embedded in the text. The Jira REST API returns nested JSON across multiple endpoints that still needs assembly and a separate summarisation step before it is useful inside an agent.