Skip to main content

View the Skill

Check out the complete Jira issue-to-PR skill with the polling script and setup reference.
When a Jira ticket is ready for engineering work, creating a GitHub pull request still requires a developer to manually pick up the ticket, create a branch, and open a PR. OpenHands can automate that handoff: a polling automation watches your Jira project for issues carrying a configurable label, and for each new one it clones the repository, implements the change, and opens a pull request—then posts a comment on the Jira ticket with a link to the live conversation.

Overview

The automation runs entirely through Agent Canvas. Each polling cycle is lightweight (no LLM calls); compute costs are only incurred when a new, unprocessed issue is found and a conversation is started. The automation:
  • Polls on a schedule — runs every N minutes using a cron trigger to check Jira for open issues with the target label
  • Deduplicates automatically — records processed issue keys so the same ticket never triggers a second PR
  • Spawns an agent per issue — starts an independent OpenHands conversation for each new issue, which reads the ticket description, clones the target GitHub repository, implements the requested change, and opens a pull request
  • Comments on the ticket — posts “I’m on it: <conversation URL>” on the Jira issue so the reporter can follow along in real time

How It Works

  1. Poll — every N minutes, the script calls the Jira Cloud search API to find open issues labeled with the configured label (default: create-pr) that have been updated since the automation was first deployed.
  2. Deduplicate — on the very first run, a baseline timestamp (first_run_at) is written to the KV store. Issues updated before that timestamp are skipped, preventing a backlog blast on first deploy. Subsequent runs skip any issue key already stored in processed_keys.
  3. Dispatch — for each new issue, an agent conversation is started. The agent is instructed to extract the GitHub repository reference (owner/repo format or a full GitHub URL) from the ticket body, then clone the repository, create a branch, implement the changes described in the ticket, and open a pull request.
  4. Comment — immediately after the conversation starts, the script posts a comment on the Jira issue: “I’m on it: <conversation URL>”.
  5. Persist — the issue key is written to processed_keys in the KV store so it is permanently skipped on future runs.

Prerequisites

Before setting up the automation, ensure the following are in place:

Storing Secrets

Go to Settings → Secrets in Agent Canvas and add:
  • JIRA_CLOUD_KEY — your Jira API token (the name is configurable; match it to jira_token_secret in the setup prompt below)
  • GITHUB_TOKEN — your GitHub personal access token with repo and workflow scopes

Automate This

You can set up this automation from any Agent Canvas conversation using the skill. Copy this prompt and fill in your details before sending it:
The automation uses the jira-issue-to-pr skill. If Agent Canvas does not have the skill installed, add it first with /add-skill https://github.com/OpenHands/extensions/tree/main/skills/jira-issue-to-pr, then resend the prompt.

Writing Jira Tickets for This Automation

Each Jira ticket that should trigger a PR must include the target GitHub repository in its body. The agent looks for an owner/repo reference or a full GitHub URL. For example:
The more context the ticket provides—file paths, acceptance criteria, test requirements—the better the resulting pull request will be.

Known Limitations

Pre-existing issues updated after deployment — The deduplication filter checks whether an issue’s updated timestamp is newer than first_run_at. If a pre-existing issue already carries the create-pr label at deploy time and is later updated for any reason (a comment, a priority change), its updated timestamp advances past first_run_at and it can slip through until it is added to processed_keys. To avoid this, use a label that is only applied to new issues after the automation is deployed—not one that may already be on existing tickets. Once an issue is processed, its key is permanently written to processed_keys and will never be dispatched again.